update
This commit is contained in:
BIN
__pycache__/event_time_specify.cpython-39.pyc
Normal file
BIN
__pycache__/event_time_specify.cpython-39.pyc
Normal file
Binary file not shown.
BIN
__pycache__/imgs_inference.cpython-39.pyc
Normal file
BIN
__pycache__/imgs_inference.cpython-39.pyc
Normal file
Binary file not shown.
BIN
__pycache__/move_detect.cpython-39.pyc
Normal file
BIN
__pycache__/move_detect.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
contrast/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
contrast/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
209
contrast/genfeats.py
Normal file
209
contrast/genfeats.py
Normal file
@ -0,0 +1,209 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Sun Nov 3 12:05:19 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
import torch
|
||||
import pickle
|
||||
import numpy as np
|
||||
from config import config as conf
|
||||
from model import resnet18 as resnet18
|
||||
from feat_inference import inference_image
|
||||
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
|
||||
|
||||
'''======= 0. 配置特征提取模型地址 ======='''
|
||||
model_path = conf.test_model
|
||||
model_path = r"D:\exhibition\ckpt\zhanting.pth"
|
||||
|
||||
##============ load resnet mdoel
|
||||
model = resnet18().to(conf.device)
|
||||
# model = nn.DataParallel(model).to(conf.device)
|
||||
model.load_state_dict(torch.load(model_path, map_location=conf.device))
|
||||
model.eval()
|
||||
print('load model {} '.format(conf.testbackbone))
|
||||
|
||||
def get_std_barcodeDict(bcdpath, savepath):
|
||||
'''
|
||||
inputs:
|
||||
bcdpath: 已清洗的barcode样本图像,如果barcode下有'base'文件夹,只选用该文件夹下图像
|
||||
(default = r'\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_1771')
|
||||
功能:
|
||||
生成并保存只有一个key值的字典 {barcode: [imgpath1, imgpath1, ...]},
|
||||
savepath: 字典存储地址,文件名格式:barcode.pickle
|
||||
'''
|
||||
|
||||
# savepath = r'\\192.168.1.28\share\测试_202406\contrast\std_barcodes'
|
||||
|
||||
'''读取数据集中 barcode 列表'''
|
||||
stdBarcodeList = []
|
||||
for filename in os.listdir(bcdpath):
|
||||
filepath = os.path.join(bcdpath, filename)
|
||||
# if not os.path.isdir(filepath) or not filename.isdigit() or len(filename)<8:
|
||||
# continue
|
||||
stdBarcodeList.append(filename)
|
||||
|
||||
bcdPaths = [(barcode, os.path.join(bcdpath, barcode)) for barcode in stdBarcodeList]
|
||||
|
||||
'''遍历数据集,针对每一个barcode,生成并保存字典{barcode: [imgpath1, imgpath1, ...]}'''
|
||||
k = 0
|
||||
errbarcodes = []
|
||||
for barcode, bpath in bcdPaths:
|
||||
pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
if os.path.isfile(pickpath):
|
||||
continue
|
||||
|
||||
stdBarcodeDict = {}
|
||||
stdBarcodeDict[barcode] = []
|
||||
for root, dirs, files in os.walk(bpath):
|
||||
imgpaths = []
|
||||
if "base" in dirs:
|
||||
broot = os.path.join(root, "base")
|
||||
for imgname in os.listdir(broot):
|
||||
imgpath = os.path.join(broot, imgname)
|
||||
file, ext = os.path.splitext(imgpath)
|
||||
|
||||
if ext not in IMG_FORMAT:
|
||||
continue
|
||||
imgpaths.append(imgpath)
|
||||
|
||||
stdBarcodeDict[barcode].extend(imgpaths)
|
||||
break
|
||||
|
||||
else:
|
||||
for imgname in files:
|
||||
imgpath = os.path.join(root, imgname)
|
||||
_, ext = os.path.splitext(imgpath)
|
||||
if ext not in IMG_FORMAT: continue
|
||||
imgpaths.append(imgpath)
|
||||
stdBarcodeDict[barcode].extend(imgpaths)
|
||||
|
||||
pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
with open(pickpath, 'wb') as f:
|
||||
pickle.dump(stdBarcodeDict, f)
|
||||
print(f"Barcode: {barcode}")
|
||||
|
||||
# k += 1
|
||||
# if k == 10:
|
||||
# break
|
||||
print(f"Len of errbarcodes: {len(errbarcodes)}")
|
||||
return
|
||||
|
||||
|
||||
|
||||
def stdfeat_infer(imgPath, featPath, bcdSet=None):
|
||||
'''
|
||||
inputs:
|
||||
imgPath: 该文件夹下的 pickle 文件格式 {barcode: [imgpath1, imgpath1, ...]}
|
||||
featPath: imgPath图像对应特征的存储地址
|
||||
功能:
|
||||
对 imgPath中图像进行特征提取,生成只有一个key值的字典,
|
||||
{barcode: features},features.shape=(nsample, 256),并保存至 featPath 中
|
||||
|
||||
'''
|
||||
|
||||
# imgPath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes"
|
||||
# featPath = r"\\192.168.1.28\share\测试_202406\contrast\std_features"
|
||||
stdBarcodeDict = {}
|
||||
stdBarcodeDict_ft16 = {}
|
||||
|
||||
|
||||
'''4处同名: (1)barcode原始图像文件夹; (2)imgPath中的 .pickle 文件名、该pickle文件中字典的key值'''
|
||||
|
||||
k = 0
|
||||
for filename in os.listdir(imgPath):
|
||||
bcd, ext = os.path.splitext(filename)
|
||||
pkpath = os.path.join(featPath, f"{bcd}.pickle")
|
||||
|
||||
if os.path.isfile(pkpath): continue
|
||||
if bcdSet is not None and bcd not in bcdSet:
|
||||
continue
|
||||
|
||||
filepath = os.path.join(imgPath, filename)
|
||||
|
||||
stdbDict = {}
|
||||
stdbDict_ft16 = {}
|
||||
stdbDict_uint8 = {}
|
||||
|
||||
t1 = time.time()
|
||||
|
||||
try:
|
||||
with open(filepath, 'rb') as f:
|
||||
bpDict = pickle.load(f)
|
||||
for barcode, imgpaths in bpDict.items():
|
||||
# feature = batch_inference(imgpaths, 8) #from vit distilled model of LiChen
|
||||
feature = inference_image(imgpaths, conf.test_transform, model, conf.device)
|
||||
feature /= np.linalg.norm(feature, axis=1)[:, None]
|
||||
|
||||
# float16
|
||||
feature_ft16 = feature.astype(np.float16)
|
||||
feature_ft16 /= np.linalg.norm(feature_ft16, axis=1)[:, None]
|
||||
|
||||
# uint8, 两种策略,1) 精度损失小, 2) 计算复杂度小
|
||||
# feature_uint8, _ = ft16_to_uint8(feature_ft16)
|
||||
feature_uint8 = (feature_ft16*128).astype(np.int8)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error accured at: {filename}, with Exception is: {e}")
|
||||
|
||||
'''================ 保存单个barcode特征 ================'''
|
||||
##================== float32
|
||||
stdbDict["barcode"] = barcode
|
||||
stdbDict["imgpaths"] = imgpaths
|
||||
stdbDict["feats_ft32"] = feature
|
||||
stdbDict["feats_ft16"] = feature_ft16
|
||||
stdbDict["feats_uint8"] = feature_uint8
|
||||
|
||||
with open(pkpath, 'wb') as f:
|
||||
pickle.dump(stdbDict, f)
|
||||
|
||||
stdBarcodeDict[barcode] = feature
|
||||
stdBarcodeDict_ft16[barcode] = feature_ft16
|
||||
|
||||
t2 = time.time()
|
||||
print(f"Barcode: {barcode}, need time: {t2-t1:.1f} secs")
|
||||
# k += 1
|
||||
# if k == 10:
|
||||
# break
|
||||
|
||||
##================== float32
|
||||
# pickpath = os.path.join(featPath, f"barcode_features_{k}.pickle")
|
||||
# with open(pickpath, 'wb') as f:
|
||||
# pickle.dump(stdBarcodeDict, f)
|
||||
|
||||
##================== float16
|
||||
# pickpath_ft16 = os.path.join(featPath, f"barcode_features_ft16_{k}.pickle")
|
||||
# with open(pickpath_ft16, 'wb') as f:
|
||||
# pickle.dump(stdBarcodeDict_ft16, f)
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
def genfeatures(imgpath, bcdpath, featpath):
|
||||
|
||||
get_std_barcodeDict(imgpath, bcdpath)
|
||||
stdfeat_infer(bcdpath, featpath, bcdSet=None)
|
||||
|
||||
print(f"Features have generated, saved in: {featpath}")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
imgpath = r"\\192.168.1.28\share\展厅barcode数据\整理\zhantingBase"
|
||||
bcdpath = r"D:\exhibition\dataset\bcdpath"
|
||||
featpath = r"D:\exhibition\dataset\feats"
|
||||
|
||||
genfeatures(imgpath, bcdpath, featpath)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -16,60 +16,13 @@ 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
|
||||
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
|
||||
|
||||
|
||||
|
||||
def showHist(err, correct):
|
||||
err = np.array(err)
|
||||
correct = np.array(correct)
|
||||
|
||||
fig, axs = plt.subplots(2, 1)
|
||||
axs[0].hist(err, bins=50, edgecolor='black')
|
||||
axs[0].set_xlim([0, 1])
|
||||
axs[0].set_title('err')
|
||||
|
||||
axs[1].hist(correct, bins=50, edgecolor='black')
|
||||
axs[1].set_xlim([0, 1])
|
||||
axs[1].set_title('correct')
|
||||
# plt.show()
|
||||
|
||||
return plt
|
||||
|
||||
def show_recall_prec(recall, prec, ths):
|
||||
# x = np.linspace(start=-0, stop=1, num=11, endpoint=True).tolist()
|
||||
fig = plt.figure(figsize=(10, 6))
|
||||
plt.plot(ths, recall, color='red', label='recall')
|
||||
plt.plot(ths, prec, color='blue', label='PrecisePos')
|
||||
plt.legend()
|
||||
plt.xlabel(f'threshold')
|
||||
# plt.ylabel('Similarity')
|
||||
plt.grid(True, linestyle='--', alpha=0.5)
|
||||
# plt.savefig('accuracy_recall_grid.png')
|
||||
# plt.show()
|
||||
# plt.close()
|
||||
|
||||
return plt
|
||||
|
||||
|
||||
def compute_recall_precision(err_similarity, correct_similarity):
|
||||
ths = np.linspace(0, 1, 51)
|
||||
recall, prec = [], []
|
||||
for th in ths:
|
||||
TP = len([num for num in correct_similarity if num >= th])
|
||||
FP = len([num for num in err_similarity if num >= th])
|
||||
if (TP+FP) == 0:
|
||||
prec.append(1)
|
||||
recall.append(0)
|
||||
else:
|
||||
prec.append(TP / (TP + FP))
|
||||
recall.append(TP / (len(err_similarity) + len(correct_similarity)))
|
||||
return recall, prec, ths
|
||||
from contrast.utils.tools import showHist, show_recall_prec, compute_recall_precision
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@ -287,27 +240,9 @@ def save_tracking_imgpairs(pair, basepath, savepath):
|
||||
cv2.imwrite(imgpath, img)
|
||||
|
||||
|
||||
# def performance_evaluate(all_list, isshow=False):
|
||||
|
||||
# corrpairs, correct_barcode_list, correct_similarity, errpairs, err_barcode_list, 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 = [float(s.strip()) for s in s_list['similarity']]
|
||||
|
||||
# if delete in barcodes[:1]:
|
||||
# corrpairs.append((seqdir, delete))
|
||||
# correct_barcode_list.append(delete)
|
||||
# correct_similarity.append(similarity[0])
|
||||
# else:
|
||||
# errpairs.append((seqdir, delete, barcodes[0]))
|
||||
# err_barcode_list.append(delete)
|
||||
# err_similarity.append(similarity[0])
|
||||
|
||||
def performance_evaluate(all_list, isshow=False):
|
||||
|
||||
corrpairs, correct_barcode_list, correct_similarity, errpairs, err_barcode_list, err_similarity = [], [], [], [], [], []
|
||||
def one2n_old(all_list):
|
||||
corrpairs, errpairs, correct_similarity, err_similarity = [], [], [], []
|
||||
for s_list in all_list:
|
||||
seqdir = s_list['SeqDir'].strip()
|
||||
delete = s_list['Deleted'].strip()
|
||||
@ -332,70 +267,136 @@ def performance_evaluate(all_list, isshow=False):
|
||||
matched_barcode = barcodes[index]
|
||||
if matched_barcode == delete:
|
||||
corrpairs.append((seqdir, delete))
|
||||
correct_barcode_list.append(delete)
|
||||
correct_similarity.append(max(similarity))
|
||||
else:
|
||||
errpairs.append((seqdir, delete, matched_barcode))
|
||||
err_barcode_list.append(delete)
|
||||
err_similarity.append(max(similarity))
|
||||
|
||||
'''3. 计算比对性能 '''
|
||||
if isshow:
|
||||
recall, prec, ths = compute_recall_precision(err_similarity, correct_similarity)
|
||||
show_recall_prec(recall, prec, ths)
|
||||
showHist(err_similarity, correct_similarity)
|
||||
|
||||
return corrpairs, errpairs, correct_similarity, err_similarity
|
||||
|
||||
|
||||
|
||||
def one2n_new(all_list):
|
||||
corrpairs, correct_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]))
|
||||
correct_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]
|
||||
|
||||
errpairs.append((seqdir, events[idxmax], events[index]))
|
||||
err_similarity.append(max(similarity))
|
||||
|
||||
|
||||
return errpairs, corrpairs, err_similarity, correct_similarity
|
||||
|
||||
|
||||
|
||||
def contrast_analysis(del_barcode_file, basepath, savepath, saveimgs=False):
|
||||
# def contrast_analysis(del_barcode_file, basepath, savepath, saveimgs=False):
|
||||
def get_relative_paths(del_barcode_file, basepath, savepath, saveimgs=False):
|
||||
'''
|
||||
del_barcode_file: 测试数据文件,利用该文件进行算法性能分析
|
||||
|
||||
del_barcode_file:
|
||||
deletedBarcode.txt 格式的 1:n 数据结果文件
|
||||
returnGoods.txt格式数据文件不需要调用该函数,one2n_old() 函数返回的 errpairs
|
||||
中元素为三元元组(取出,放入, 错误匹配)
|
||||
'''
|
||||
relative_paths = []
|
||||
|
||||
'''1. 读取 deletedBarcode 文件 '''
|
||||
all_list = read_deletedBarcode_file(del_barcode_file)
|
||||
|
||||
'''2. 算法性能评估,并输出 (取出,删除, 错误匹配) 对 '''
|
||||
errpairs, corrpairs, _, _ = performance_evaluate(all_list)
|
||||
errpairs, corrpairs, _, _ = one2n_old(all_list)
|
||||
|
||||
'''3. 获取 (取出,删除, 错误匹配) 对应路径,保存相应轨迹图像'''
|
||||
relative_paths = []
|
||||
'''3. 构造事件组合(取出,放入并删除, 错误匹配) 对应路径 '''
|
||||
for errpair in errpairs:
|
||||
GetoutPath, InputPath, ErrorPath = get_contrast_paths(errpair, basepath)
|
||||
relative_paths.append((GetoutPath, InputPath, ErrorPath))
|
||||
|
||||
'''3. 获取 (取出,放入并删除, 错误匹配) 对应路径,保存相应轨迹图像'''
|
||||
if saveimgs:
|
||||
save_tracking_imgpairs(errpair, basepath, savepath)
|
||||
|
||||
return relative_paths
|
||||
|
||||
|
||||
def contrast_loop(fpath):
|
||||
def one2n_test():
|
||||
fpath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\other'
|
||||
fpath = r'\\192.168.1.28\share\测试_202406\1030\images'
|
||||
|
||||
savepath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\illustration'
|
||||
# savepath = r'D:\contrast\dataset\1_to_n\illustration'
|
||||
if not os.path.exists(savepath):
|
||||
os.mkdir(savepath)
|
||||
|
||||
if os.path.isfile(fpath):
|
||||
fpath, filename = os.path.split(fpath)
|
||||
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
|
||||
|
||||
|
||||
FileFormat = {}
|
||||
|
||||
BarLists, blists = {}, []
|
||||
for filename in os.listdir(fpath):
|
||||
file = os.path.splitext(filename)[0][15:]
|
||||
for pth in filepaths:
|
||||
file = str(Path(pth).stem)
|
||||
if file.find('deletedBarcode')>=0:
|
||||
FileFormat[file] = 'deletedBarcode'
|
||||
blist = read_deletedBarcode_file(pth)
|
||||
elif file.find('returnGoods')>=0:
|
||||
FileFormat[file] = 'returnGoods'
|
||||
blist = read_returnGoods_file(pth)
|
||||
else:
|
||||
return
|
||||
|
||||
filepath = os.path.join(fpath, filename)
|
||||
blist = read_deletedBarcode_file(filepath)
|
||||
|
||||
BarLists.update({file: blist})
|
||||
blists.extend(blist)
|
||||
|
||||
BarLists.update({file: blist})
|
||||
BarLists.update({"Total": blists})
|
||||
|
||||
for file, blist in BarLists.items():
|
||||
errpairs, corrpairs, err_similarity, correct_similarity = performance_evaluate(blist)
|
||||
if FileFormat[file] == 'deletedBarcode':
|
||||
_, _, err_similarity, correct_similarity = one2n_old(blist)
|
||||
elif FileFormat[file] == 'returnGoods':
|
||||
_, _, err_similarity, correct_similarity = one2n_new(blist)
|
||||
else:
|
||||
_, _, err_similarity, correct_similarity = one2n_old(blist)
|
||||
|
||||
|
||||
recall, prec, ths = compute_recall_precision(err_similarity, correct_similarity)
|
||||
|
||||
@ -411,25 +412,33 @@ def contrast_loop(fpath):
|
||||
# plt.close()
|
||||
|
||||
|
||||
def main():
|
||||
fpath = r'\\192.168.1.28\share\测试_202406\deletedBarcode\other'
|
||||
contrast_loop(fpath)
|
||||
|
||||
def main1():
|
||||
|
||||
def test_getreltpath():
|
||||
'''
|
||||
适用于:deletedBarcode.txt,不适用于:returnGoods.txt
|
||||
'''
|
||||
|
||||
del_barcode_file = r'\\192.168.1.28\share\测试_202406\709\deletedBarcode.txt'
|
||||
basepath = r'\\192.168.1.28\share\测试_202406\709'
|
||||
savepath = r'D:\contrast\dataset\result'
|
||||
|
||||
# del_barcode_file = r'\\192.168.1.28\share\测试_202406\1030\images\returnGoods.txt'
|
||||
# basepath = r'\\192.168.1.28\share\测试_202406\1030\images'
|
||||
|
||||
savepath = r'D:\contrast\dataset\result'
|
||||
saveimgs = True
|
||||
try:
|
||||
relative_path = contrast_analysis(del_barcode_file, basepath, savepath)
|
||||
relative_path = get_relative_paths(del_barcode_file, basepath, savepath, saveimgs)
|
||||
except Exception as e:
|
||||
print(f'Error Type: {e}')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# main1()
|
||||
one2n_test()
|
||||
|
||||
# test_getreltpath()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -239,71 +239,71 @@ def creat_shopping_event(eventPath, subimgPath=False):
|
||||
|
||||
return event
|
||||
|
||||
def get_std_barcodeDict(bcdpath, savepath):
|
||||
'''
|
||||
inputs:
|
||||
bcdpath: 已清洗的barcode样本图像,如果barcode下有'base'文件夹,只选用该文件夹下图像
|
||||
(default = r'\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_1771')
|
||||
功能:
|
||||
生成并保存只有一个key值的字典 {barcode: [imgpath1, imgpath1, ...]},
|
||||
savepath: 字典存储地址,文件名格式:barcode.pickle
|
||||
'''
|
||||
# def get_std_barcodeDict(bcdpath, savepath):
|
||||
# '''
|
||||
# inputs:
|
||||
# bcdpath: 已清洗的barcode样本图像,如果barcode下有'base'文件夹,只选用该文件夹下图像
|
||||
# (default = r'\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_1771')
|
||||
# 功能:
|
||||
# 生成并保存只有一个key值的字典 {barcode: [imgpath1, imgpath1, ...]},
|
||||
# savepath: 字典存储地址,文件名格式:barcode.pickle
|
||||
# '''
|
||||
|
||||
# savepath = r'\\192.168.1.28\share\测试_202406\contrast\std_barcodes'
|
||||
# # savepath = r'\\192.168.1.28\share\测试_202406\contrast\std_barcodes'
|
||||
|
||||
'''读取数据集中 barcode 列表'''
|
||||
stdBarcodeList = []
|
||||
for filename in os.listdir(bcdpath):
|
||||
filepath = os.path.join(bcdpath, filename)
|
||||
# if not os.path.isdir(filepath) or not filename.isdigit() or len(filename)<8:
|
||||
# continue
|
||||
stdBarcodeList.append(filename)
|
||||
# '''读取数据集中 barcode 列表'''
|
||||
# stdBarcodeList = []
|
||||
# for filename in os.listdir(bcdpath):
|
||||
# filepath = os.path.join(bcdpath, filename)
|
||||
# # if not os.path.isdir(filepath) or not filename.isdigit() or len(filename)<8:
|
||||
# # continue
|
||||
# stdBarcodeList.append(filename)
|
||||
|
||||
bcdPaths = [(barcode, os.path.join(bcdpath, barcode)) for barcode in stdBarcodeList]
|
||||
# bcdPaths = [(barcode, os.path.join(bcdpath, barcode)) for barcode in stdBarcodeList]
|
||||
|
||||
'''遍历数据集,针对每一个barcode,生成并保存字典{barcode: [imgpath1, imgpath1, ...]}'''
|
||||
k = 0
|
||||
errbarcodes = []
|
||||
for barcode, bpath in bcdPaths:
|
||||
pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
if os.path.isfile(pickpath):
|
||||
continue
|
||||
# '''遍历数据集,针对每一个barcode,生成并保存字典{barcode: [imgpath1, imgpath1, ...]}'''
|
||||
# k = 0
|
||||
# errbarcodes = []
|
||||
# for barcode, bpath in bcdPaths:
|
||||
# pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
# if os.path.isfile(pickpath):
|
||||
# continue
|
||||
|
||||
stdBarcodeDict = {}
|
||||
stdBarcodeDict[barcode] = []
|
||||
for root, dirs, files in os.walk(bpath):
|
||||
imgpaths = []
|
||||
if "base" in dirs:
|
||||
broot = os.path.join(root, "base")
|
||||
for imgname in os.listdir(broot):
|
||||
imgpath = os.path.join(broot, imgname)
|
||||
file, ext = os.path.splitext(imgpath)
|
||||
# stdBarcodeDict = {}
|
||||
# stdBarcodeDict[barcode] = []
|
||||
# for root, dirs, files in os.walk(bpath):
|
||||
# imgpaths = []
|
||||
# if "base" in dirs:
|
||||
# broot = os.path.join(root, "base")
|
||||
# for imgname in os.listdir(broot):
|
||||
# imgpath = os.path.join(broot, imgname)
|
||||
# file, ext = os.path.splitext(imgpath)
|
||||
|
||||
if ext not in IMG_FORMAT:
|
||||
continue
|
||||
imgpaths.append(imgpath)
|
||||
# if ext not in IMG_FORMAT:
|
||||
# continue
|
||||
# imgpaths.append(imgpath)
|
||||
|
||||
stdBarcodeDict[barcode].extend(imgpaths)
|
||||
break
|
||||
# stdBarcodeDict[barcode].extend(imgpaths)
|
||||
# break
|
||||
|
||||
else:
|
||||
for imgname in files:
|
||||
imgpath = os.path.join(root, imgname)
|
||||
_, ext = os.path.splitext(imgpath)
|
||||
if ext not in IMG_FORMAT: continue
|
||||
imgpaths.append(imgpath)
|
||||
stdBarcodeDict[barcode].extend(imgpaths)
|
||||
# else:
|
||||
# for imgname in files:
|
||||
# imgpath = os.path.join(root, imgname)
|
||||
# _, ext = os.path.splitext(imgpath)
|
||||
# if ext not in IMG_FORMAT: continue
|
||||
# imgpaths.append(imgpath)
|
||||
# stdBarcodeDict[barcode].extend(imgpaths)
|
||||
|
||||
pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
with open(pickpath, 'wb') as f:
|
||||
pickle.dump(stdBarcodeDict, f)
|
||||
print(f"Barcode: {barcode}")
|
||||
# pickpath = os.path.join(savepath, f"{barcode}.pickle")
|
||||
# with open(pickpath, 'wb') as f:
|
||||
# pickle.dump(stdBarcodeDict, f)
|
||||
# print(f"Barcode: {barcode}")
|
||||
|
||||
# k += 1
|
||||
# if k == 10:
|
||||
# break
|
||||
print(f"Len of errbarcodes: {len(errbarcodes)}")
|
||||
return
|
||||
# # k += 1
|
||||
# # if k == 10:
|
||||
# # break
|
||||
# print(f"Len of errbarcodes: {len(errbarcodes)}")
|
||||
# return
|
||||
|
||||
def save_event_subimg(event, savepath):
|
||||
'''
|
||||
@ -355,92 +355,92 @@ def batch_inference(imgpaths, batch):
|
||||
features = np.concatenate(features, axis=0)
|
||||
return features
|
||||
|
||||
def stdfeat_infer(imgPath, featPath, bcdSet=None):
|
||||
'''
|
||||
inputs:
|
||||
imgPath: 该文件夹下的 pickle 文件格式 {barcode: [imgpath1, imgpath1, ...]}
|
||||
featPath: imgPath图像对应特征的存储地址
|
||||
功能:
|
||||
对 imgPath中图像进行特征提取,生成只有一个key值的字典,
|
||||
{barcode: features},features.shape=(nsample, 256),并保存至 featPath 中
|
||||
# def stdfeat_infer(imgPath, featPath, bcdSet=None):
|
||||
# '''
|
||||
# inputs:
|
||||
# imgPath: 该文件夹下的 pickle 文件格式 {barcode: [imgpath1, imgpath1, ...]}
|
||||
# featPath: imgPath图像对应特征的存储地址
|
||||
# 功能:
|
||||
# 对 imgPath中图像进行特征提取,生成只有一个key值的字典,
|
||||
# {barcode: features},features.shape=(nsample, 256),并保存至 featPath 中
|
||||
|
||||
'''
|
||||
# '''
|
||||
|
||||
# imgPath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes"
|
||||
# featPath = r"\\192.168.1.28\share\测试_202406\contrast\std_features"
|
||||
stdBarcodeDict = {}
|
||||
stdBarcodeDict_ft16 = {}
|
||||
# # imgPath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes"
|
||||
# # featPath = r"\\192.168.1.28\share\测试_202406\contrast\std_features"
|
||||
# stdBarcodeDict = {}
|
||||
# stdBarcodeDict_ft16 = {}
|
||||
|
||||
|
||||
'''4处同名: (1)barcode原始图像文件夹; (2)imgPath中的 .pickle 文件名、该pickle文件中字典的key值'''
|
||||
# '''4处同名: (1)barcode原始图像文件夹; (2)imgPath中的 .pickle 文件名、该pickle文件中字典的key值'''
|
||||
|
||||
k = 0
|
||||
for filename in os.listdir(imgPath):
|
||||
bcd, ext = os.path.splitext(filename)
|
||||
pkpath = os.path.join(featPath, f"{bcd}.pickle")
|
||||
# k = 0
|
||||
# for filename in os.listdir(imgPath):
|
||||
# bcd, ext = os.path.splitext(filename)
|
||||
# pkpath = os.path.join(featPath, f"{bcd}.pickle")
|
||||
|
||||
if os.path.isfile(pkpath): continue
|
||||
if bcdSet is not None and bcd not in bcdSet:
|
||||
continue
|
||||
# if os.path.isfile(pkpath): continue
|
||||
# if bcdSet is not None and bcd not in bcdSet:
|
||||
# continue
|
||||
|
||||
filepath = os.path.join(imgPath, filename)
|
||||
# filepath = os.path.join(imgPath, filename)
|
||||
|
||||
stdbDict = {}
|
||||
stdbDict_ft16 = {}
|
||||
stdbDict_uint8 = {}
|
||||
# stdbDict = {}
|
||||
# stdbDict_ft16 = {}
|
||||
# stdbDict_uint8 = {}
|
||||
|
||||
t1 = time.time()
|
||||
# t1 = time.time()
|
||||
|
||||
try:
|
||||
with open(filepath, 'rb') as f:
|
||||
bpDict = pickle.load(f)
|
||||
for barcode, imgpaths in bpDict.items():
|
||||
# feature = batch_inference(imgpaths, 8) #from vit distilled model of LiChen
|
||||
feature = inference_image(imgpaths, conf.test_transform, model, conf.device)
|
||||
feature /= np.linalg.norm(feature, axis=1)[:, None]
|
||||
# try:
|
||||
# with open(filepath, 'rb') as f:
|
||||
# bpDict = pickle.load(f)
|
||||
# for barcode, imgpaths in bpDict.items():
|
||||
# # feature = batch_inference(imgpaths, 8) #from vit distilled model of LiChen
|
||||
# feature = inference_image(imgpaths, conf.test_transform, model, conf.device)
|
||||
# feature /= np.linalg.norm(feature, axis=1)[:, None]
|
||||
|
||||
# float16
|
||||
feature_ft16 = feature.astype(np.float16)
|
||||
feature_ft16 /= np.linalg.norm(feature_ft16, axis=1)[:, None]
|
||||
# # float16
|
||||
# feature_ft16 = feature.astype(np.float16)
|
||||
# feature_ft16 /= np.linalg.norm(feature_ft16, axis=1)[:, None]
|
||||
|
||||
# uint8, 两种策略,1) 精度损失小, 2) 计算复杂度小
|
||||
# feature_uint8, _ = ft16_to_uint8(feature_ft16)
|
||||
feature_uint8 = (feature_ft16*128).astype(np.int8)
|
||||
# # uint8, 两种策略,1) 精度损失小, 2) 计算复杂度小
|
||||
# # feature_uint8, _ = ft16_to_uint8(feature_ft16)
|
||||
# feature_uint8 = (feature_ft16*128).astype(np.int8)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error accured at: {filename}, with Exception is: {e}")
|
||||
# except Exception as e:
|
||||
# print(f"Error accured at: {filename}, with Exception is: {e}")
|
||||
|
||||
'''================ 保存单个barcode特征 ================'''
|
||||
##================== float32
|
||||
stdbDict["barcode"] = barcode
|
||||
stdbDict["imgpaths"] = imgpaths
|
||||
stdbDict["feats_ft32"] = feature
|
||||
stdbDict["feats_ft16"] = feature_ft16
|
||||
stdbDict["feats_uint8"] = feature_uint8
|
||||
# '''================ 保存单个barcode特征 ================'''
|
||||
# ##================== float32
|
||||
# stdbDict["barcode"] = barcode
|
||||
# stdbDict["imgpaths"] = imgpaths
|
||||
# stdbDict["feats_ft32"] = feature
|
||||
# stdbDict["feats_ft16"] = feature_ft16
|
||||
# stdbDict["feats_uint8"] = feature_uint8
|
||||
|
||||
with open(pkpath, 'wb') as f:
|
||||
pickle.dump(stdbDict, f)
|
||||
# with open(pkpath, 'wb') as f:
|
||||
# pickle.dump(stdbDict, f)
|
||||
|
||||
stdBarcodeDict[barcode] = feature
|
||||
stdBarcodeDict_ft16[barcode] = feature_ft16
|
||||
# stdBarcodeDict[barcode] = feature
|
||||
# stdBarcodeDict_ft16[barcode] = feature_ft16
|
||||
|
||||
t2 = time.time()
|
||||
print(f"Barcode: {barcode}, need time: {t2-t1:.1f} secs")
|
||||
# k += 1
|
||||
# if k == 10:
|
||||
# break
|
||||
# t2 = time.time()
|
||||
# print(f"Barcode: {barcode}, need time: {t2-t1:.1f} secs")
|
||||
# # k += 1
|
||||
# # if k == 10:
|
||||
# # break
|
||||
|
||||
##================== float32
|
||||
# pickpath = os.path.join(featPath, f"barcode_features_{k}.pickle")
|
||||
# with open(pickpath, 'wb') as f:
|
||||
# pickle.dump(stdBarcodeDict, f)
|
||||
# ##================== float32
|
||||
# # pickpath = os.path.join(featPath, f"barcode_features_{k}.pickle")
|
||||
# # with open(pickpath, 'wb') as f:
|
||||
# # pickle.dump(stdBarcodeDict, f)
|
||||
|
||||
##================== float16
|
||||
# pickpath_ft16 = os.path.join(featPath, f"barcode_features_ft16_{k}.pickle")
|
||||
# with open(pickpath_ft16, 'wb') as f:
|
||||
# pickle.dump(stdBarcodeDict_ft16, f)
|
||||
# ##================== float16
|
||||
# # pickpath_ft16 = os.path.join(featPath, f"barcode_features_ft16_{k}.pickle")
|
||||
# # with open(pickpath_ft16, 'wb') as f:
|
||||
# # pickle.dump(stdBarcodeDict_ft16, f)
|
||||
|
||||
return
|
||||
# return
|
||||
|
||||
|
||||
def contrast_performance_evaluate(resultPath):
|
||||
@ -789,30 +789,28 @@ def main():
|
||||
compute_precise_recall(pickpath)
|
||||
|
||||
|
||||
def main_std():
|
||||
std_sample_path = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_500_2192_已清洗"
|
||||
std_barcode_path = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192"
|
||||
std_feature_path = r"\\192.168.1.28\share\测试_202406\contrast\std_features_2192_ft32vsft16"
|
||||
# def main_std():
|
||||
# std_sample_path = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_500_2192_已清洗"
|
||||
# std_barcode_path = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192"
|
||||
# std_feature_path = r"\\192.168.1.28\share\测试_202406\contrast\std_features_2192_ft32vsft16"
|
||||
|
||||
get_std_barcodeDict(std_sample_path, std_barcode_path)
|
||||
|
||||
stdfeat_infer(std_barcode_path, std_feature_path, bcdSet=None)
|
||||
# get_std_barcodeDict(std_sample_path, std_barcode_path)
|
||||
# stdfeat_infer(std_barcode_path, std_feature_path, bcdSet=None)
|
||||
|
||||
# fileList = []
|
||||
# for filename in os.listdir(std_barcode_path):
|
||||
# filepath = os.path.join(std_barcode_path, filename)
|
||||
# with open(filepath, 'rb') as f:
|
||||
# bpDict = pickle.load(f)
|
||||
# # fileList = []
|
||||
# # for filename in os.listdir(std_barcode_path):
|
||||
# # filepath = os.path.join(std_barcode_path, filename)
|
||||
# # with open(filepath, 'rb') as f:
|
||||
# # bpDict = pickle.load(f)
|
||||
|
||||
# for v in bpDict.values():
|
||||
# fileList.append(len(v))
|
||||
# print("done")
|
||||
# # for v in bpDict.values():
|
||||
# # fileList.append(len(v))
|
||||
# # print("done")
|
||||
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
|
||||
|
||||
main_std()
|
||||
main()
|
||||
# main_std()
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Sep 11 11:57:30 2024
|
||||
|
||||
永辉现场 1:1 比对测试
|
||||
|
||||
永辉现场试验输出数据的 1:1 性能评估
|
||||
适用于202410前数据保存版本的,需调用 OneToOneCompare.txt
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
@ -65,14 +64,14 @@ def plot_pr_curve(matrix):
|
||||
axs[1].set_title(f'Cross Barcode, Num: {TPFN_mean}')
|
||||
# plt.savefig(f'./result/{file}_hist.png') # svg, png, pdf
|
||||
|
||||
Recall_Pos = []
|
||||
Recall_Neg = []
|
||||
Thresh = np.linspace(-0.2, 1, 100)
|
||||
for th in Thresh:
|
||||
TN = np.sum(simimax < th)
|
||||
Recall_Pos.append(TN/TPFN_max)
|
||||
Recall_Neg.append(TN/TPFN_max)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, Recall_Pos, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, Recall_Neg, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
@ -96,10 +95,8 @@ def main():
|
||||
simiList = []
|
||||
for fp in filepaths:
|
||||
slist = read_one2one_data(fp)
|
||||
|
||||
simiList.extend(slist)
|
||||
|
||||
|
||||
plot_pr_curve(simiList)
|
||||
|
||||
|
||||
|
BIN
contrast/utils/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
contrast/utils/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
contrast/utils/__pycache__/tools.cpython-39.pyc
Normal file
BIN
contrast/utils/__pycache__/tools.cpython-39.pyc
Normal file
Binary file not shown.
56
contrast/utils/tools.py
Normal file
56
contrast/utils/tools.py
Normal file
@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Oct 31 15:17:01 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
|
||||
def showHist(err, correct):
|
||||
err = np.array(err)
|
||||
correct = np.array(correct)
|
||||
|
||||
fig, axs = plt.subplots(2, 1)
|
||||
axs[0].hist(err, bins=50, edgecolor='black')
|
||||
axs[0].set_xlim([0, 1])
|
||||
axs[0].set_title('err')
|
||||
|
||||
axs[1].hist(correct, bins=50, edgecolor='black')
|
||||
axs[1].set_xlim([0, 1])
|
||||
axs[1].set_title('correct')
|
||||
# plt.show()
|
||||
|
||||
return plt
|
||||
|
||||
def show_recall_prec(recall, prec, ths):
|
||||
# x = np.linspace(start=-0, stop=1, num=11, endpoint=True).tolist()
|
||||
fig = plt.figure(figsize=(10, 6))
|
||||
plt.plot(ths, recall, color='red', label='recall')
|
||||
plt.plot(ths, prec, color='blue', label='PrecisePos')
|
||||
plt.legend()
|
||||
plt.xlabel(f'threshold')
|
||||
# plt.ylabel('Similarity')
|
||||
plt.grid(True, linestyle='--', alpha=0.5)
|
||||
# plt.savefig('accuracy_recall_grid.png')
|
||||
# plt.show()
|
||||
# plt.close()
|
||||
|
||||
return plt
|
||||
|
||||
|
||||
def compute_recall_precision(err_similarity, correct_similarity):
|
||||
ths = np.linspace(0, 1, 51)
|
||||
recall, prec = [], []
|
||||
for th in ths:
|
||||
TP = len([num for num in correct_similarity if num >= th])
|
||||
FP = len([num for num in err_similarity if num >= th])
|
||||
if (TP+FP) == 0:
|
||||
prec.append(1)
|
||||
recall.append(0)
|
||||
else:
|
||||
prec.append(TP / (TP + FP))
|
||||
recall.append(TP / (len(err_similarity) + len(correct_similarity)))
|
||||
return recall, prec, ths
|
301
event_time_specify.py
Normal file
301
event_time_specify.py
Normal file
@ -0,0 +1,301 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Oct 10 11:01:39 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import numpy as np
|
||||
# from matplotlib.pylab import mpl
|
||||
# mpl.use('Qt5Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
from move_detect import MoveDetect
|
||||
|
||||
|
||||
import sys
|
||||
sys.path.append(r"D:\DetectTracking")
|
||||
|
||||
# from tracking.utils.read_data import extract_data, read_deletedBarcode_file, read_tracking_output, read_weight_timeConsuming
|
||||
|
||||
|
||||
from tracking.utils.read_data import read_weight_timeConsuming
|
||||
|
||||
def str_to_float_arr(s):
|
||||
# 移除字符串末尾的逗号(如果存在)
|
||||
if s.endswith(','):
|
||||
s = s[:-1]
|
||||
|
||||
# 使用split()方法分割字符串,然后将每个元素转化为float
|
||||
float_array = [float(x) for x in s.split(",")]
|
||||
return float_array
|
||||
|
||||
def find_samebox_in_array(arr, target):
|
||||
|
||||
for i, st in enumerate(arr):
|
||||
if st[:4] == target[:4]:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def array2frame(bboxes):
|
||||
frameID = np.sort(np.unique(bboxes[:, 7].astype(int)))
|
||||
# frame_ids = bboxes[:, frameID].astype(int)
|
||||
fboxes, ttamps = [], []
|
||||
for fid in frameID:
|
||||
idx = np.where(bboxes[:, 7] == fid)[0]
|
||||
box = bboxes[idx, :]
|
||||
|
||||
fboxes.append(box)
|
||||
ttamps.append(int(box[0, 9]))
|
||||
|
||||
frameTstamp = np.concatenate((frameID[:,None], np.array(ttamps)[:,None]), axis=1)
|
||||
|
||||
return fboxes, frameTstamp
|
||||
|
||||
|
||||
def extract_data_1(datapath):
|
||||
'''
|
||||
要求每一帧(包括最后一帧)输出数据后有一空行作为分割行,该分割行为标志行
|
||||
'''
|
||||
|
||||
trackerboxes = np.empty((0, 10), dtype=np.float64)
|
||||
trackerfeats = np.empty((0, 256), dtype=np.float64)
|
||||
|
||||
boxes, feats, tboxes, tfeats = [], [], [], []
|
||||
timestamp = -1
|
||||
|
||||
newframe = False
|
||||
with open(datapath, 'r', encoding='utf-8') as lines:
|
||||
for line in lines:
|
||||
if line.find("CameraId")>=0:
|
||||
newframe = True
|
||||
timestamp, frameId = [int(ln.split(":")[1]) for ln in line.split(",")[1:]]
|
||||
# boxes, feats, tboxes, tfeats = [], [], [], []
|
||||
|
||||
|
||||
if line.find("box:") >= 0 and line.find("output_box:") < 0:
|
||||
line = line.strip()
|
||||
box = line[line.find("box:") + 4:].strip()
|
||||
# if len(box)==6:
|
||||
boxes.append(str_to_float_arr(box))
|
||||
|
||||
if line.find("feat:") >= 0:
|
||||
line = line.strip()
|
||||
feat = line[line.find("feat:") + 5:].strip()
|
||||
# if len(feat)==256:
|
||||
feats.append(str_to_float_arr(feat))
|
||||
|
||||
if line.find("output_box:") >= 0:
|
||||
line = line.strip()
|
||||
# 确保 boxes 和 feats 一一对应,并可以保证 tboxes 和 tfeats 一一对应
|
||||
if len(boxes)==0 or len(boxes)!=len(feats):
|
||||
continue
|
||||
|
||||
box = str_to_float_arr(line[line.find("output_box:") + 11:].strip())
|
||||
|
||||
box.append(timestamp)
|
||||
index = find_samebox_in_array(boxes, box)
|
||||
if index >= 0:
|
||||
tboxes.append(box) # 去掉'output_box:'并去除可能的空白字符
|
||||
|
||||
# feat_f = str_to_float_arr(input_feats[index])
|
||||
feat_f = feats[index]
|
||||
norm_f = np.linalg.norm(feat_f)
|
||||
feat_f = feat_f / norm_f
|
||||
tfeats.append(feat_f)
|
||||
|
||||
'''标志行(空行)判断'''
|
||||
condt = line.find("timestamp")<0 and line.find("box:")<0 and line.find("feat:")<0
|
||||
if condt and newframe:
|
||||
if len(tboxes) and len(tfeats):
|
||||
trackerboxes = np.concatenate((trackerboxes, np.array(tboxes)))
|
||||
trackerfeats = np.concatenate((trackerfeats, np.array(tfeats)))
|
||||
|
||||
timestamp = -1
|
||||
boxes, feats, tboxes, tfeats = [], [], [], []
|
||||
newframe = False
|
||||
|
||||
return trackerboxes, trackerfeats
|
||||
|
||||
|
||||
def devide_motion_state(tboxes, width):
|
||||
'''frameTstamp: 用于标记当前相机视野内用购物车运动状态变化'''
|
||||
|
||||
periods = []
|
||||
if len(tboxes) < width:
|
||||
return periods
|
||||
|
||||
fboxes, frameTstamp = array2frame(tboxes)
|
||||
|
||||
fnum = len(frameTstamp)
|
||||
if fnum < width: return periods
|
||||
|
||||
state = np.zeros((fnum, 2), dtype=np.int64)
|
||||
frameState = np.concatenate((frameTstamp, state), axis = 1).astype(np.int64)
|
||||
|
||||
mtrackFid = {}
|
||||
'''frameState 标记由图像判断的购物车状态:0: 静止,1: 运动'''
|
||||
for idx in range(width, fnum+1):
|
||||
lboxes = np.concatenate(fboxes[idx-width:idx], axis = 0)
|
||||
|
||||
md = MoveDetect(lboxes)
|
||||
md.classify()
|
||||
|
||||
# if idx==60:
|
||||
# print('a')
|
||||
|
||||
## track.during 二元素组, 表征在该时间片段内,轨迹 track 的起止时间,数值用 boxes[:, 7]
|
||||
for track in md.track_motion:
|
||||
if track.cls == 0: continue
|
||||
|
||||
|
||||
|
||||
f1, f2 = track.during
|
||||
|
||||
|
||||
|
||||
idx1 = set(np.where(frameState[:,0] >= f1)[0])
|
||||
idx2 = set(np.where(frameState[:,0] <= f2)[0])
|
||||
idx3 = list(idx1.intersection(idx2))
|
||||
|
||||
if track.tid not in mtrackFid:
|
||||
mtrackFid[track.tid] = set(idx3)
|
||||
else:
|
||||
mtrackFid[track.tid] = mtrackFid[track.tid].union(set(idx3))
|
||||
|
||||
frameState[idx-1, 3] = 1
|
||||
frameState[idx3, 2] = 1
|
||||
|
||||
'''状态变化输出'''
|
||||
|
||||
for tid, fid in mtrackFid.items():
|
||||
fstate = np.zeros((fnum, 1), dtype=np.int64)
|
||||
fstate[list(fid), 0] = tid
|
||||
|
||||
frameState = np.concatenate((frameState, fstate), axis = 1).astype(np.int64)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return frameState
|
||||
|
||||
|
||||
def state_measure(periods, weights, spath=None):
|
||||
'''两种状态:static、motion,
|
||||
(t0, t1)
|
||||
t0: static ----> motion
|
||||
t1: motion ----> static
|
||||
'''
|
||||
|
||||
PrevState = 'static'
|
||||
CuurState = 'static'
|
||||
|
||||
camtype_0, frstate_0 = periods[0]
|
||||
camtype_1, frstate_1 = periods[1]
|
||||
|
||||
'''计算总时间区间: tmin, tmax, during'''
|
||||
tmin_w, tmax_w = np.min(weights[:, 0]), np.max(weights[:, 0])
|
||||
tmin_0, tmax_0 = np.min(frstate_0[:, 1]), np.max(frstate_0[:, 1])
|
||||
tmin_1, tmax_1 = np.min(frstate_1[:, 1]), np.max(frstate_1[:, 1])
|
||||
|
||||
tmin = min([tmin_w, tmin_0, tmin_1])
|
||||
tmax = max([tmax_w, tmax_0, tmax_1])
|
||||
|
||||
# for ctype, tboxes, _ in tracker_boxes:
|
||||
# t_min, t_max = np.min(tboxes[:, 9]), np.max(tboxes[:, 9])
|
||||
# if t_min<tmin:
|
||||
# tmin = t_min
|
||||
# if t_max>tmax:
|
||||
# tmax = t_max
|
||||
# during = tmax - tmin
|
||||
|
||||
|
||||
|
||||
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)
|
||||
|
||||
ax1.plot(weights[:, 0] - tmin, weights[:, 1], 'bo-', linewidth=1, markersize=4)
|
||||
# ax1.set_xlim([0, during])
|
||||
ax1.set_title('Weight (g)')
|
||||
|
||||
ax2.plot(frstate_0[:, 1] - tmin, frstate_0[:, 2], 'rx-', linewidth=1, markersize=8)
|
||||
ax2.plot(frstate_0[:, 1] - tmin, frstate_0[:, 3], 'bo-', linewidth=1, markersize=4)
|
||||
# ax2.set_xlim([0, during])
|
||||
ax2.set_title(f'Camera: {int(camtype_0)}')
|
||||
|
||||
ax3.plot(frstate_1[:, 1] - tmin, frstate_1[:, 2], 'rx-', linewidth=1, markersize=8)
|
||||
ax3.plot(frstate_1[:, 1] - tmin, frstate_1[:, 3], 'bo-', linewidth=1, markersize=4)
|
||||
ax3.set_title(f'Camera: {int(camtype_1)}')
|
||||
|
||||
if spath:
|
||||
plt.savefig(spath)
|
||||
plt.show()
|
||||
|
||||
def read_yolo_weight_data(eventdir):
|
||||
filepaths = []
|
||||
for filename in os.listdir(eventdir):
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext =='.data':
|
||||
filepath = os.path.join(eventdir, filename)
|
||||
filepaths.append(filepath)
|
||||
|
||||
if len(filepaths) != 5:
|
||||
return
|
||||
|
||||
tracker_boxes = []
|
||||
WeightDict, SensorDict, ProcessTimeDict = {}, {}, {}
|
||||
for filepath in filepaths:
|
||||
filename = os.path.basename(filepath)
|
||||
|
||||
if filename.find('_track.data')>0:
|
||||
CamerType = filename.split('_')[0]
|
||||
trackerboxes, trackerfeats = extract_data_1(filepath)
|
||||
tracker_boxes.append((CamerType, trackerboxes, trackerfeats))
|
||||
|
||||
if filename.find('process.data')==0:
|
||||
WeightDict, SensorDict, ProcessTimeDict = read_weight_timeConsuming(filepath)
|
||||
|
||||
'''====================重力信号处理===================='''
|
||||
weights = [(float(t), w) for t, w in WeightDict.items()]
|
||||
weights = np.array(weights)
|
||||
|
||||
return tracker_boxes, weights
|
||||
|
||||
|
||||
def main():
|
||||
eventdir = r"\\192.168.1.28\share\测试_202406\0819\images\20240817-192549-6940120c-634c-481b-97a6-65042729f86b_null"
|
||||
|
||||
tracker_boxes, weights = read_yolo_weight_data(eventdir)
|
||||
|
||||
'''====================图像运动分析===================='''
|
||||
win_width = 12
|
||||
periods = []
|
||||
for ctype, tboxes, _ in tracker_boxes:
|
||||
period = devide_motion_state(tboxes, win_width)
|
||||
|
||||
periods.append((ctype, period))
|
||||
print('done!')
|
||||
|
||||
'''===============重力、图像信息融合==================='''
|
||||
state_measure(periods, weights)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
435
imgs_inference.py
Normal file
435
imgs_inference.py
Normal file
@ -0,0 +1,435 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Fri Oct 18 13:09:42 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import torch
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
|
||||
# from matplotlib.pylab import mpl
|
||||
# mpl.use('Qt5Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
FILE = Path(__file__).resolve()
|
||||
ROOT = FILE.parents[0] # YOLOv5 root directory
|
||||
if str(ROOT) not in sys.path:
|
||||
sys.path.append(str(ROOT)) # add ROOT to PATH
|
||||
ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
|
||||
|
||||
from models.common import DetectMultiBackend
|
||||
|
||||
from utils.augmentations import letterbox
|
||||
|
||||
|
||||
from utils.general import (LOGGER, Profile, check_file, check_img_size, check_imshow, check_requirements, colorstr, cv2,
|
||||
increment_path, non_max_suppression, print_args, scale_boxes, strip_optimizer, xyxy2xywh)
|
||||
from utils.torch_utils import select_device, smart_inference_mode
|
||||
|
||||
'''集成跟踪模块,输出跟踪结果文件 .npy'''
|
||||
# from ultralytics.engine.results import Boxes # Results
|
||||
# from ultralytics.utils import IterableSimpleNamespace, yaml_load
|
||||
from tracking.utils.plotting import Annotator, colors
|
||||
from tracking.utils import Boxes, IterableSimpleNamespace, yaml_load, boxes_add_fid
|
||||
from tracking.trackers import BOTSORT, BYTETracker
|
||||
from tracking.utils.showtrack import drawtracks
|
||||
from hands.hand_inference import hand_pose
|
||||
|
||||
from tracking.trackers.reid.reid_interface import ReIDInterface
|
||||
from tracking.trackers.reid.config import config as ReIDConfig
|
||||
|
||||
ReIDEncoder = ReIDInterface(ReIDConfig)
|
||||
IMG_FORMATS = 'bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm' # include image suffixes
|
||||
VID_FORMATS = 'asf', 'avi', 'gif', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ts', 'wmv' # include video suffixes
|
||||
|
||||
class LoadImages:
|
||||
# YOLOv5 image/video dataloader, i.e. `python detect.py --source image.jpg/vid.mp4`
|
||||
def __init__(self, files, img_size=640, stride=32, auto=True, transforms=None, vid_stride=1):
|
||||
images = [x for x in files if x.split('.')[-1].lower() in IMG_FORMATS]
|
||||
videos = [x for x in files if x.split('.')[-1].lower() in VID_FORMATS]
|
||||
ni, nv = len(images), len(videos)
|
||||
|
||||
|
||||
|
||||
self.img_size = img_size
|
||||
self.stride = stride
|
||||
self.files = images + videos
|
||||
self.nf = ni + nv # number of files
|
||||
self.video_flag = [False] * ni + [True] * nv
|
||||
self.mode = 'image'
|
||||
self.auto = auto
|
||||
self.transforms = transforms # optional
|
||||
self.vid_stride = vid_stride # video frame-rate stride
|
||||
if any(videos):
|
||||
self._new_video(videos[0]) # new video
|
||||
else:
|
||||
self.cap = None
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
self.count = 0
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.count == self.nf:
|
||||
raise StopIteration
|
||||
path = self.files[self.count]
|
||||
|
||||
if self.video_flag[self.count]:
|
||||
# Read video
|
||||
self.mode = 'video'
|
||||
for _ in range(self.vid_stride):
|
||||
self.cap.grab()
|
||||
ret_val, im0 = self.cap.retrieve()
|
||||
while not ret_val:
|
||||
self.count += 1
|
||||
self.cap.release()
|
||||
if self.count == self.nf: # last video
|
||||
raise StopIteration
|
||||
path = self.files[self.count]
|
||||
self._new_video(path)
|
||||
ret_val, im0 = self.cap.read()
|
||||
|
||||
self.frame += 1
|
||||
# im0 = self._cv2_rotate(im0) # for use if cv2 autorotation is False
|
||||
s = f'video {self.count + 1}/{self.nf} ({self.frame}/{self.frames}) {path}: '
|
||||
|
||||
else:
|
||||
# Read image
|
||||
self.count += 1
|
||||
im0 = cv2.imread(path) # BGR
|
||||
|
||||
# image rorate
|
||||
(h, w) = im0.shape[:2]
|
||||
center = (w // 2, h // 2)
|
||||
angle = 90
|
||||
scale = 1.0
|
||||
M = cv2.getRotationMatrix2D(center, angle, scale)
|
||||
im0 = cv2.warpAffine(im0, M, (h, w))
|
||||
|
||||
assert im0 is not None, f'Image Not Found {path}'
|
||||
s = f'image {self.count}/{self.nf} {path}: '
|
||||
|
||||
if self.transforms:
|
||||
im = self.transforms(im0) # transforms
|
||||
else:
|
||||
im = letterbox(im0, self.img_size, stride=self.stride, auto=self.auto)[0] # padded resize
|
||||
im = im.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
|
||||
im = np.ascontiguousarray(im) # contiguous
|
||||
|
||||
return path, im, im0, self.cap, s
|
||||
|
||||
def _new_video(self, path):
|
||||
# Create a new video capture object
|
||||
self.frame = 0
|
||||
self.cap = cv2.VideoCapture(path)
|
||||
self.frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT) / self.vid_stride)
|
||||
self.orientation = int(self.cap.get(cv2.CAP_PROP_ORIENTATION_META)) # rotation degrees
|
||||
# self.cap.set(cv2.CAP_PROP_ORIENTATION_AUTO, 0) # disable https://github.com/ultralytics/yolov5/issues/8493
|
||||
|
||||
def _cv2_rotate(self, im):
|
||||
# Rotate a cv2 video manually
|
||||
if self.orientation == 0:
|
||||
return cv2.rotate(im, cv2.ROTATE_90_CLOCKWISE)
|
||||
elif self.orientation == 180:
|
||||
return cv2.rotate(im, cv2.ROTATE_90_COUNTERCLOCKWISE)
|
||||
elif self.orientation == 90:
|
||||
return cv2.rotate(im, cv2.ROTATE_180)
|
||||
return im
|
||||
|
||||
def __len__(self):
|
||||
return self.nf # number of files
|
||||
|
||||
def inference_image(image, detections):
|
||||
H, W, _ = np.shape(image)
|
||||
imgs = []
|
||||
batch_patches = []
|
||||
patches = []
|
||||
for d in range(np.size(detections, 0)):
|
||||
tlbr = detections[d, :4].astype(np.int_)
|
||||
tlbr[0] = max(0, tlbr[0])
|
||||
tlbr[1] = max(0, tlbr[1])
|
||||
tlbr[2] = min(W - 1, tlbr[2])
|
||||
tlbr[3] = min(H - 1, tlbr[3])
|
||||
img1 = image[tlbr[1]:tlbr[3], tlbr[0]:tlbr[2], :]
|
||||
|
||||
img = img1[:, :, ::-1].copy() # the model expects RGB inputs
|
||||
patch = ReIDEncoder.transform(img)
|
||||
|
||||
imgs.append(img1)
|
||||
# patch = patch.to(device=self.device).half()
|
||||
if str(ReIDEncoder.device) != "cpu":
|
||||
patch = patch.to(device=ReIDEncoder.device).half()
|
||||
else:
|
||||
patch = patch.to(device=ReIDEncoder.device)
|
||||
|
||||
patches.append(patch)
|
||||
if (d + 1) % ReIDEncoder.batch_size == 0:
|
||||
patches = torch.stack(patches, dim=0)
|
||||
batch_patches.append(patches)
|
||||
patches = []
|
||||
|
||||
if len(patches):
|
||||
patches = torch.stack(patches, dim=0)
|
||||
batch_patches.append(patches)
|
||||
|
||||
features = np.zeros((0, ReIDEncoder.embedding_size))
|
||||
for patches in batch_patches:
|
||||
pred = ReIDEncoder.model(patches)
|
||||
pred[torch.isinf(pred)] = 1.0
|
||||
feat = pred.cpu().data.numpy()
|
||||
features = np.vstack((features, feat))
|
||||
|
||||
return imgs, features
|
||||
|
||||
|
||||
def init_trackers(tracker_yaml = None, bs=1):
|
||||
"""
|
||||
Initialize trackers for object tracking during prediction.
|
||||
"""
|
||||
# tracker_yaml = r"./tracking/trackers/cfg/botsort.yaml"
|
||||
|
||||
TRACKER_MAP = {'bytetrack': BYTETracker, 'botsort': BOTSORT}
|
||||
|
||||
cfg = IterableSimpleNamespace(**yaml_load(tracker_yaml))
|
||||
trackers = []
|
||||
for _ in range(bs):
|
||||
tracker = TRACKER_MAP[cfg.tracker_type](args=cfg, frame_rate=30)
|
||||
trackers.append(tracker)
|
||||
|
||||
return trackers
|
||||
|
||||
|
||||
def run(
|
||||
weights=ROOT / 'yolov5s.pt', # model path or triton URL
|
||||
source=ROOT / 'data/images', # file/dir/URL/glob/screen/0(webcam)
|
||||
|
||||
project=ROOT / 'runs/detect', # save results to project/name
|
||||
name='exp', # save results to project/name
|
||||
|
||||
tracker_yaml = "./tracking/trackers/cfg/botsort.yaml",
|
||||
imgsz=(640, 640), # inference size (height, width)
|
||||
conf_thres=0.25, # confidence threshold
|
||||
iou_thres=0.45, # NMS IOU threshold
|
||||
max_det=1000, # maximum detections per image
|
||||
device='', # cuda device, i.e. 0 or 0,1,2,3 or cpu
|
||||
view_img=False, # show results
|
||||
save_txt=False, # save results to *.txt
|
||||
save_csv=False, # save results in CSV format
|
||||
save_conf=False, # save confidences in --save-txt labels
|
||||
save_crop=False, # save cropped prediction boxes
|
||||
save_img = True,
|
||||
nosave=False, # do not save images/videos
|
||||
classes=None, # filter by class: --class 0, or --class 0 2 3
|
||||
agnostic_nms=False, # class-agnostic NMS
|
||||
augment=False, # augmented inference
|
||||
visualize=False, # visualize features
|
||||
update=False, # update all models
|
||||
exist_ok=False, # existing project/name ok, do not increment
|
||||
line_thickness=3, # bounding box thickness (pixels)
|
||||
hide_labels=False, # hide labels
|
||||
hide_conf=False, # hide confidencesL
|
||||
half=False, # use FP16 half-precision inference
|
||||
dnn=False, # use OpenCV DNN for ONNX inference
|
||||
vid_stride=1, # video frame-rate stride
|
||||
data=ROOT / 'data/coco128.yaml', # dataset.yaml path
|
||||
):
|
||||
assert isinstance(source,list), "source must be a list"
|
||||
|
||||
fulldir, imgname = os.path.split(source[0])
|
||||
imgbase, ext = os.path.splitext(imgname)
|
||||
|
||||
|
||||
# 事件名、相机类型
|
||||
EventName = fulldir.split('\\')[-2] + "_" + str(Path(fulldir).stem)
|
||||
CamerType = imgbase.split('_')[1]
|
||||
|
||||
save_dir = Path(project) / Path(EventName)
|
||||
if save_dir.exists():
|
||||
print(Path(fulldir).stem)
|
||||
|
||||
# save_dir = increment_path(Path(project) / name, exist_ok=exist_ok) # increment run
|
||||
# save_dir.mkdir(parents=True, exist_ok=True) # make dir
|
||||
else:
|
||||
save_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
save_path_video = os.path.join(str(save_dir), f"{EventName}_{CamerType}")
|
||||
# Load model
|
||||
device = select_device(device)
|
||||
model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
|
||||
stride, names, pt = model.stride, model.names, model.pt
|
||||
imgsz = check_img_size(imgsz, s=stride) # check image size
|
||||
|
||||
bs = 1 # batch_size
|
||||
|
||||
dataset = LoadImages(source, img_size=imgsz, stride=stride, auto=pt, vid_stride=vid_stride)
|
||||
vid_path, vid_writer = [None] * bs, [None] * bs
|
||||
|
||||
# Run inference
|
||||
model.warmup(imgsz=(1 if pt or model.triton else bs, 3, *imgsz)) # warmup
|
||||
seen, dt = 0, (Profile(), Profile(), Profile())
|
||||
|
||||
tracker = init_trackers(tracker_yaml, bs)[0]
|
||||
track_boxes = np.empty((0, 10), dtype = np.float32)
|
||||
k = 0
|
||||
for path, im, im0s, vid_cap, s in dataset:
|
||||
# k +=1
|
||||
# if k==60:
|
||||
# break
|
||||
|
||||
timeStamp = Path(path).stem.split('_')[2]
|
||||
|
||||
with dt[0]:
|
||||
im = torch.from_numpy(im).to(model.device)
|
||||
im = im.half() if model.fp16 else im.float() # uint8 to fp16/32
|
||||
im /= 255 # 0 - 255 to 0.0 - 1.0
|
||||
if len(im.shape) == 3:
|
||||
im = im[None] # expand for batch dim
|
||||
|
||||
# Inference
|
||||
with dt[1]:
|
||||
visualize = increment_path(save_dir / Path(path).stem, mkdir=True) if visualize else False
|
||||
pred = model(im, augment=augment, visualize=visualize)
|
||||
|
||||
# NMS
|
||||
with dt[2]:
|
||||
pred = non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
|
||||
|
||||
# Process predictions
|
||||
for i, det in enumerate(pred): # per image
|
||||
seen += 1
|
||||
im0 = im0s.copy()
|
||||
|
||||
s += '%gx%g ' % im.shape[2:] # print string
|
||||
annotator = Annotator(im0s, line_width=line_thickness, example=str(names))
|
||||
|
||||
nd = len(det)
|
||||
if nd:
|
||||
# Rescale boxes from img_size to im0 size
|
||||
det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()
|
||||
|
||||
'''tracks: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index, timestamp]
|
||||
0 1 2 3 4 5 6 7 8
|
||||
这里,frame_index 也可以用视频的 帧ID 代替, box_index 保持不变
|
||||
'''
|
||||
|
||||
det_tracking = Boxes(det, im0.shape).cpu().numpy()
|
||||
tracks = tracker.update(det_tracking, im0)
|
||||
if len(tracks) == 0:
|
||||
continue
|
||||
tracks[:, 7] = dataset.count
|
||||
|
||||
|
||||
stamp = np.ones((len(tracks), 1)) * int(timeStamp)
|
||||
tracks = np.concatenate((tracks, stamp), axis=1)
|
||||
|
||||
'''================== 1. 存储 dets/subimgs/features Dict ============='''
|
||||
# imgs, features = inference_image(im0, tracks)
|
||||
track_boxes = np.concatenate([track_boxes, tracks], axis=0)
|
||||
|
||||
for *xyxy, id, conf, cls, fid, bid, t in reversed(tracks):
|
||||
name = ('' if id==-1 else f'id:{int(id)} ') + names[int(cls)]
|
||||
label = None if hide_labels else (name if hide_conf else f'{name} {conf:.2f}')
|
||||
|
||||
if id >=0 and cls==0:
|
||||
color = colors(int(cls), True)
|
||||
elif id >=0 and cls!=0:
|
||||
color = colors(int(id), True)
|
||||
else:
|
||||
color = colors(19, True) # 19为调色板的最后一个元素
|
||||
|
||||
annotator.box_label(xyxy, label, color=color)
|
||||
|
||||
# Save results (image and video with tracking)
|
||||
im0 = annotator.result()
|
||||
p = Path(path) # to Path
|
||||
if save_img:
|
||||
imgpath = str(save_dir/p.stem) + f"_{dataset.count}.png"
|
||||
cv2.imwrite(Path(imgpath), im0)
|
||||
if vid_path[i] != save_path_video: # new video
|
||||
vid_path[i] = save_path_video
|
||||
if isinstance(vid_writer[i], cv2.VideoWriter):
|
||||
vid_writer[i].release() # release previous video writer
|
||||
fps, w, h = 30, im0.shape[1], im0.shape[0]
|
||||
vpath = str(Path(save_path_video).with_suffix('.mp4'))
|
||||
vid_writer[i] = cv2.VideoWriter(vpath, cv2.VideoWriter_fourcc(*'mp4v'), fps, (w, h))
|
||||
|
||||
vid_writer[i].write(im0)
|
||||
|
||||
LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{dt[1].dt * 1E3:.1f}ms")
|
||||
|
||||
for v in vid_writer:
|
||||
v.release()
|
||||
|
||||
if track_boxes.size == 0:
|
||||
return CamerType, []
|
||||
|
||||
save_path_np = os.path.join(str(fulldir), f"{EventName}_{CamerType}")
|
||||
np.save(save_path_np, track_boxes)
|
||||
|
||||
# Print results
|
||||
t = tuple(x.t / seen * 1E3 for x in dt) # speeds per image
|
||||
LOGGER.info(f'Speed: %.1fms pre-process, %.1fms inference, %.1fms NMS per image at shape {(1, 3, *imgsz)}' % t)
|
||||
if save_txt or save_img:
|
||||
s = f"\n{len(list(save_dir.glob('labels/*.txt')))} labels saved to {save_dir / 'labels'}" if save_txt else ''
|
||||
LOGGER.info(f"Results saved to {colorstr('bold', save_dir)}{s}")
|
||||
if update:
|
||||
strip_optimizer(weights[0]) # update model (to fix SourceChangeWarning)
|
||||
|
||||
|
||||
return CamerType, track_boxes
|
||||
|
||||
|
||||
def parse_opt():
|
||||
modelpath = ROOT / 'ckpts/best_cls10_0906.pt' # 'ckpts/best_15000_0908.pt', 'ckpts/yolov5s.pt', 'ckpts/best_20000_cls30.pt, best_yolov5m_250000'
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--weights', nargs='+', type=str, default=modelpath, help='model path or triton URL') # 'yolov5s.pt', best_15000_0908.pt
|
||||
parser.add_argument('--source', type=str, default='', help='file/dir/URL/glob/screen/0(webcam)') # images, videos
|
||||
parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='(optional) dataset.yaml path')
|
||||
parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640], help='inference size h,w')
|
||||
parser.add_argument('--conf-thres', type=float, default=0.25, help='confidence threshold')
|
||||
parser.add_argument('--iou-thres', type=float, default=0.45, help='NMS IoU threshold')
|
||||
parser.add_argument('--max-det', type=int, default=1000, help='maximum detections per image')
|
||||
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
|
||||
parser.add_argument('--view-img', action='store_true', help='show results')
|
||||
parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
|
||||
parser.add_argument('--save-csv', action='store_true', help='save results in CSV format')
|
||||
parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
|
||||
parser.add_argument('--save-crop', action='store_true', help='save cropped prediction boxes')
|
||||
parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
|
||||
parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --classes 0, or --classes 0 2 3')
|
||||
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
|
||||
parser.add_argument('--augment', action='store_true', help='augmented inference')
|
||||
parser.add_argument('--visualize', action='store_true', help='visualize features')
|
||||
parser.add_argument('--update', action='store_true', help='update all models')
|
||||
parser.add_argument('--project', default=ROOT / 'runs/detect', help='save results to project/name')
|
||||
parser.add_argument('--name', default='exp', help='save results to project/name')
|
||||
parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
|
||||
parser.add_argument('--line-thickness', default=3, type=int, help='bounding box thickness (pixels)')
|
||||
parser.add_argument('--hide-labels', default=False, action='store_true', help='hide labels')
|
||||
parser.add_argument('--hide-conf', default=False, action='store_true', help='hide confidences')
|
||||
parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')
|
||||
parser.add_argument('--dnn', action='store_true', help='use OpenCV DNN for ONNX inference')
|
||||
parser.add_argument('--vid-stride', type=int, default=1, help='video frame-rate stride')
|
||||
opt = parser.parse_args()
|
||||
opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1 # expand
|
||||
print_args(vars(opt))
|
||||
return opt
|
||||
|
||||
def run_yolo(eventdir, savedir):
|
||||
|
||||
opt = parse_opt()
|
||||
optdict = vars(opt)
|
||||
optdict["project"] = savedir
|
||||
optdict["source"] = eventdir
|
||||
run(**vars(opt))
|
||||
|
||||
|
||||
|
||||
|
||||
|
243
move_detect.py
Normal file
243
move_detect.py
Normal file
@ -0,0 +1,243 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Oct 14 10:01:24 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import numpy as np
|
||||
import cv2
|
||||
from scipy.spatial.distance import cdist
|
||||
|
||||
|
||||
class TrackFrag:
|
||||
|
||||
def __init__(self, boxes, imgshape=(1280, 1024)):
|
||||
self.boxes = boxes
|
||||
self.cls = int(boxes[0, 6])
|
||||
self.tid = int(boxes[0, 4])
|
||||
self.imgshape = imgshape
|
||||
|
||||
|
||||
'''轨迹的持续时间,以帧ID表征, (或考虑用时间戳)'''
|
||||
self.during = (np.min(boxes[:, 7]), np.max(boxes[:, 7]))
|
||||
|
||||
self.groups = [set(np.unique(boxes[:, 7].astype(int)))]
|
||||
|
||||
# '''5个关键点(中心点、左上点、右上点、左下点、右下点 )坐标'''
|
||||
self.isCornpoint = self.is_cornpoint(10)
|
||||
self.compute_cornpoints()
|
||||
|
||||
|
||||
def is_cornpoint(self, edge=10):
|
||||
|
||||
isleft = min(self.boxes[:, 0]) < edge
|
||||
istop = min(self.boxes[:, 1]) < edge
|
||||
isright = max(self.boxes[:, 2]) > self.imgshape[0] - edge
|
||||
isbottom = max(self.boxes[:, 3]) > self.imgshape[0] - edge
|
||||
|
||||
isCornpoint = isbottom or istop or isleft or isright
|
||||
return isCornpoint
|
||||
|
||||
|
||||
|
||||
def compute_cornpoints(self):
|
||||
'''
|
||||
cornpoints 共10项,分别是个点的坐标值(x, y)
|
||||
(center, top_left, top_right, bottom_left, bottom_right)
|
||||
'''
|
||||
boxes = self.boxes
|
||||
cornpoints = np.zeros((len(boxes), 10))
|
||||
|
||||
cornpoints[:,0] = (boxes[:, 0] + boxes[:, 2]) / 2
|
||||
cornpoints[:,1] = (boxes[:, 1] + boxes[:, 3]) / 2
|
||||
cornpoints[:,2], cornpoints[:,3] = boxes[:, 0], boxes[:, 1]
|
||||
cornpoints[:,4], cornpoints[:,5] = boxes[:, 2], boxes[:, 1]
|
||||
cornpoints[:,6], cornpoints[:,7] = boxes[:, 0], boxes[:, 3]
|
||||
cornpoints[:,8], cornpoints[:,9] = boxes[:, 2], boxes[:, 3]
|
||||
|
||||
trajdist = []
|
||||
for k in range(5):
|
||||
X = cornpoints[:, 2*k:2*(k+1)]
|
||||
trajdist.append(np.max(cdist(X, X)))
|
||||
|
||||
idx = trajdist.index(min(trajdist))
|
||||
|
||||
self.trajdist_min = trajdist[idx]
|
||||
self.cornpoints = cornpoints
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def update_groups(self, THRESH=18):
|
||||
'''
|
||||
对 self.groups 重新赋值
|
||||
'''
|
||||
|
||||
boxes = self.boxes
|
||||
nbox = len(boxes)
|
||||
|
||||
X = np.zeros((len(boxes), 2))
|
||||
X[:,0] = (boxes[:, 0] + boxes[:, 2]) / 2
|
||||
X[:,1] = (boxes[:, 1] + boxes[:, 3]) / 2
|
||||
|
||||
dist2 = cdist(X, X)
|
||||
# label = np.zeros(nbox, dtype=np.int)
|
||||
|
||||
marked, groups = set(), []
|
||||
for k in range(nbox):
|
||||
if k in marked:
|
||||
continue
|
||||
group = set()
|
||||
|
||||
dt = dist2[k, :]
|
||||
idx = np.where(dt < THRESH)[0]
|
||||
|
||||
if len(idx) == 1:
|
||||
groups.append({k})
|
||||
marked.add(k)
|
||||
continue
|
||||
'''初始近邻样本点集合, 并移除当前点'''
|
||||
seeds = set(idx)
|
||||
seeds.remove(k)
|
||||
|
||||
group.add(k)
|
||||
marked.add(k)
|
||||
while len(seeds) !=0:
|
||||
pt = seeds.pop()
|
||||
dt = dist2[pt, :]
|
||||
|
||||
seed = set(np.where(dt < THRESH)[0])
|
||||
seed.remove(pt)
|
||||
|
||||
seed.difference_update(marked)
|
||||
seeds.update(seed)
|
||||
|
||||
group.add(pt)
|
||||
marked.add(pt)
|
||||
|
||||
groups.append(group)
|
||||
|
||||
self.groups = groups
|
||||
|
||||
|
||||
def jump_boxes(self):
|
||||
gpboxes = []
|
||||
for group in self.groups:
|
||||
box = self.boxes[list(group), :]
|
||||
gpboxes.append(box)
|
||||
|
||||
return gpboxes
|
||||
|
||||
|
||||
|
||||
def is_moving(self):
|
||||
if len(self.groups)>=3:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def is_static(self):
|
||||
box1 = self.boxes[0, :4]
|
||||
box2 = self.boxes[-1, :4]
|
||||
|
||||
''' 第1帧、最后一帧 boxes 四个角点间的距离 '''
|
||||
ptd = box2 - box1
|
||||
ptd1 = np.linalg.norm((ptd[0], ptd[1]))
|
||||
ptd2 = np.linalg.norm((ptd[2], ptd[1]))
|
||||
ptd3 = np.linalg.norm((ptd[0], ptd[3]))
|
||||
ptd4 = np.linalg.norm((ptd[2], ptd[3]))
|
||||
condt1 = ptd1<50 and ptd2<50 and ptd3<50 and ptd4<50
|
||||
|
||||
if not self.isCornpoint:
|
||||
self.trajdist_min < 120
|
||||
|
||||
|
||||
# condt2 = self.TrajFeat[3] < 50
|
||||
# condt = condt1 or condt2
|
||||
return condt1
|
||||
|
||||
|
||||
class MoveDetect:
|
||||
def __init__(self, bboxes, imgshape=(1280, 1024)):
|
||||
self.bboxes = bboxes
|
||||
self.shape = imgshape
|
||||
|
||||
self.temp = np.zeros(imgshape, np.uint8)
|
||||
|
||||
|
||||
self.trackIDs = np.unique(bboxes[:, 4].astype(int))
|
||||
# self.frameID = np.unique(bboxes[:, 7].astype(int))
|
||||
# self.fnum = len(self.frameID)
|
||||
|
||||
self.lboxes = self.array2list()
|
||||
|
||||
self.tracks = [TrackFrag(b) for b in self.lboxes]
|
||||
|
||||
def classify(self):
|
||||
|
||||
tracks = self.tracks
|
||||
|
||||
'''减去静止轨迹'''
|
||||
tracks_static = [t for t in tracks if t.is_static()]
|
||||
tracks = self.sub_tracks(tracks, tracks_static)
|
||||
|
||||
'''更新轨迹点聚类'''
|
||||
for track in tracks:
|
||||
track.update_groups(18)
|
||||
|
||||
|
||||
self.track_motion = [t for t in tracks if len(t.groups)>=3]
|
||||
|
||||
|
||||
def draw(self):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
def array2list(self):
|
||||
'''
|
||||
将 bboxes 变换为 track 列表
|
||||
bboxes: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]
|
||||
Return:
|
||||
lboxes:列表,列表中元素具有同一 track_id,x1y1x2y2 格式
|
||||
[x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]
|
||||
'''
|
||||
track_ids = self.bboxes[:, 4].astype(int)
|
||||
lboxes = []
|
||||
for t_id in self.trackIDs:
|
||||
# print(f"The ID is: {t_id}")
|
||||
idx = np.where(track_ids == t_id)[0]
|
||||
box = self.bboxes[idx, :]
|
||||
|
||||
lboxes.append(box)
|
||||
|
||||
return lboxes
|
||||
|
||||
@staticmethod
|
||||
def sub_tracks(tlista, tlistb):
|
||||
track_ids_b = {t.tid for t in tlistb}
|
||||
return [t for t in tlista if t.tid not in track_ids_b]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
147
pipeline.py
147
pipeline.py
@ -7,24 +7,20 @@ Created on Sun Sep 29 08:59:21 2024
|
||||
import os
|
||||
import cv2
|
||||
import pickle
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from track_reid import parse_opt, yolo_resnet_tracker
|
||||
|
||||
from tracking.dotrack.dotracks_back import doBackTracks
|
||||
from tracking.dotrack.dotracks_front import doFrontTracks
|
||||
from tracking.utils.drawtracks import plot_frameID_y2, draw_all_trajectories
|
||||
from utils.getsource import get_image_pairs, get_video_pairs
|
||||
|
||||
IMGFORMATS = '.bmp', '.jpeg', '.jpg', 'png', 'tif', 'tiff', 'webp', 'pfm'
|
||||
VIDFORMATS = '.avi', '.gif', '.m4v', '.mkv', '.mov', '.mp4', '.ts', '.wmv'
|
||||
|
||||
std_feature_path = r"\\192.168.1.28\share\测试_202406\contrast\std_features_2192_ft32vsft16"
|
||||
|
||||
|
||||
opt = parse_opt()
|
||||
optdict = vars(opt)
|
||||
|
||||
|
||||
|
||||
|
||||
std_feature_path = r"\\192.168.1.28\share\测试_202406\contrast\std_features_2192_ft32vsft16"
|
||||
|
||||
def get_interbcd_inputenents():
|
||||
bcdpath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192"
|
||||
@ -45,107 +41,117 @@ def get_interbcd_inputenents():
|
||||
|
||||
return input_enents
|
||||
|
||||
def pipeline(eventpath, stdfeat_path=None, SourceType = "image"):
|
||||
'''
|
||||
inputs:
|
||||
eventpath: 事件文件夹
|
||||
stdfeat_path: 标准特征文件地址
|
||||
outputs:
|
||||
|
||||
'''
|
||||
SourceType = "image" # image
|
||||
|
||||
def get_video_pairs(vpath):
|
||||
vdieopath = []
|
||||
for filename in os.listdir(vpath):
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext in VIDFORMATS:
|
||||
vdieopath.append(os.path.join(vpath, filename))
|
||||
return vdieopath
|
||||
|
||||
def pipeline(eventpath, stdfeat_path):
|
||||
# eventpath = r"\\192.168.1.28\share\测试_202406\0918\images1\20240918-110822-1bc3902e-5a8e-4e23-8eca-fb3f02738551_6938314601726"
|
||||
|
||||
savepath = r"D:\contrast\detect"
|
||||
|
||||
opt = parse_opt()
|
||||
optdict = vars(opt)
|
||||
optdict["project"] = savepath
|
||||
|
||||
eventname = os.path.basename(eventpath)
|
||||
barcode = eventname.split('_')[-1]
|
||||
# barcode = eventname.split('_')[-1]
|
||||
|
||||
|
||||
if SourceType == "video":
|
||||
vpaths = get_video_pairs(eventpath)
|
||||
elif SourceType == "image":
|
||||
vpaths = get_image_pairs(eventpath)
|
||||
|
||||
|
||||
|
||||
event_tracks = []
|
||||
for vpath in vpaths:
|
||||
|
||||
'''事件结果文件夹'''
|
||||
save_dir_event = Path(savepath) / Path(eventname)
|
||||
save_dir_img = save_dir_event / Path(str(Path(vpath).stem))
|
||||
if not save_dir_img.exists():
|
||||
save_dir_img.mkdir(parents=True, exist_ok=True)
|
||||
if isinstance(vpath, list):
|
||||
save_dir_video = save_dir_event / Path("images")
|
||||
else:
|
||||
save_dir_video = save_dir_event / Path(str(Path(vpath).stem))
|
||||
|
||||
|
||||
if not save_dir_video.exists():
|
||||
save_dir_video.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
'''Yolo + Resnet + Tracker'''
|
||||
optdict["source"] = vpath
|
||||
optdict["save_dir"] = save_dir_img
|
||||
optdict["nosave"] = False
|
||||
optdict["save_dir"] = save_dir_video
|
||||
optdict["is_save_img"] = True
|
||||
optdict["is_save_video"] = True
|
||||
|
||||
tracksdict = yolo_resnet_tracker(**optdict)
|
||||
|
||||
bboxes = tracksdict['TrackBoxes']
|
||||
|
||||
bname = os.path.basename(vpath)
|
||||
bname = os.path.basename(vpath[0]) if isinstance(vpath, list) else os.path.basename(vpath)
|
||||
if bname.split('_')[0] == "0" or bname.find('back')>=0:
|
||||
vts = doFrontTracks(bboxes, tracksdict)
|
||||
vts = doBackTracks(bboxes, tracksdict)
|
||||
vts.classify()
|
||||
|
||||
event_tracks.append(("back", vts))
|
||||
|
||||
if bname.split('_')[0] == "1" or bname.find('front')>=0:
|
||||
vts = doBackTracks(bboxes, tracksdict)
|
||||
vts = doFrontTracks(bboxes, tracksdict)
|
||||
vts.classify()
|
||||
event_tracks.append(("front", vts))
|
||||
|
||||
|
||||
'''轨迹显示模块'''
|
||||
illus = [None, None]
|
||||
for CamerType, vts in event_tracks:
|
||||
if CamerType == 'back':
|
||||
pass
|
||||
if CamerType == 'front':
|
||||
pass
|
||||
edgeline = cv2.imread("./tracking/shopcart/cart_tempt/board_ftmp_line.png")
|
||||
img_tracking = draw_all_trajectories(vts, edgeline, save_dir_event, CamerType, draw5p=True)
|
||||
illus[0] = img_tracking
|
||||
|
||||
|
||||
plt = plot_frameID_y2(vts)
|
||||
plt.savefig(os.path.join(save_dir_event, "front_y2.png"))
|
||||
|
||||
if CamerType == 'back':
|
||||
edgeline = cv2.imread("./tracking/shopcart/cart_tempt/edgeline.png")
|
||||
img_tracking = draw_all_trajectories(vts, edgeline, save_dir_event, CamerType, draw5p=True)
|
||||
illus[1] = img_tracking
|
||||
|
||||
illus = [im for im in illus if im is not None]
|
||||
if len(illus):
|
||||
img_cat = np.concatenate(illus, axis = 1)
|
||||
if len(illus)==2:
|
||||
H, W = img_cat.shape[:2]
|
||||
cv2.line(img_cat, (int(W/2), 0), (int(W/2), int(H)), (128, 128, 255), 3)
|
||||
|
||||
trajpath = os.path.join(save_dir_event, "traj.png")
|
||||
cv2.imwrite(trajpath, img_cat)
|
||||
|
||||
|
||||
|
||||
'''前后摄轨迹选择'''
|
||||
|
||||
|
||||
if stdfeat_path is not None:
|
||||
with open(stdfeat_path, 'rb') as f:
|
||||
featDict = pickle.load(f)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
def main_loop():
|
||||
bcdpath = r"\\192.168.1.28\share\测试_202406\contrast\std_barcodes_2192"
|
||||
eventpath = r"\\192.168.1.28\share\测试_202406\0918\images1"
|
||||
|
||||
SourceType = "image" # video, image
|
||||
|
||||
barcodes = []
|
||||
input_enents = []
|
||||
output_events = []
|
||||
|
||||
|
||||
# input_enents = get_interbcd_inputenents()
|
||||
# k = 0
|
||||
# for event in input_enents:
|
||||
# pipeline(event)
|
||||
|
||||
# k += 1
|
||||
# if k ==1:
|
||||
# break
|
||||
|
||||
|
||||
'''1. 获得barcode标准特征集列表'''
|
||||
for featname in os.listdir(bcdpath):
|
||||
barcode, ext = os.path.splitext(featname)
|
||||
@ -153,30 +159,29 @@ def main():
|
||||
continue
|
||||
barcodes.append(barcode)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
'''2. 构造(放入事件,标准特征)对'''
|
||||
for filename in os.listdir(eventpath):
|
||||
'''barcode为时间文件夹的最后一个字段'''
|
||||
bcd = filename.split('_')[-1]
|
||||
|
||||
event_path = os.path.join(eventpath, filename)
|
||||
stdfeat_path = None
|
||||
if bcd in barcodes:
|
||||
stdfeat_path = os.path.join(bcdpath, f"{bcd}.pickle")
|
||||
|
||||
input_enents.append((event_path, stdfeat_path))
|
||||
|
||||
|
||||
|
||||
|
||||
for eventpath, stdfeat_path in input_enents:
|
||||
pipeline(eventpath, stdfeat_path)
|
||||
pipeline(eventpath, stdfeat_path, SourceType)
|
||||
|
||||
|
||||
def main():
|
||||
eventpath = r"D:\datasets\ym\exhibition\175836"
|
||||
SourceType = 'image'
|
||||
stdfeat_path = None
|
||||
|
||||
pipeline(eventpath, stdfeat_path, SourceType)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -188,3 +193,9 @@ def main():
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
"""
|
||||
Created on Sun Sep 29 08:59:21 2024
|
||||
|
||||
针对现场采集的视频,利用算法pipeline提取运动轨迹内的subimg,代替人工图像筛选、标注
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
|
451
time_devide.py
Normal file
451
time_devide.py
Normal file
@ -0,0 +1,451 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Oct 16 17:37:07 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
||||
# import csv
|
||||
import os
|
||||
# import platform
|
||||
# import sys
|
||||
from pathlib import Path
|
||||
import glob
|
||||
import numpy as np
|
||||
import copy
|
||||
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from imgs_inference import run_yolo
|
||||
|
||||
from event_time_specify import devide_motion_state#, state_measure
|
||||
from tracking.utils.read_data import read_seneor
|
||||
|
||||
|
||||
|
||||
# IMG_FORMATS = 'bmp', 'dng', 'jpeg', 'jpg', 'mpo', 'png', 'tif', 'tiff', 'webp', 'pfm' # include image suffixes
|
||||
# VID_FORMATS = 'asf', 'avi', 'gif', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ts', 'wmv' # include video suffixes
|
||||
|
||||
|
||||
def filesort(p):
|
||||
'''
|
||||
需将图像文件名标准化
|
||||
'''
|
||||
|
||||
|
||||
files = []
|
||||
files.extend(sorted(glob.glob(os.path.join(p, '*.jpg'))))
|
||||
# images = [x for x in files if x.split('.')[-1].lower() in IMG_FORMATS]
|
||||
|
||||
tamps_0, tamps_1 = [], []
|
||||
files_0, files_1 = [], []
|
||||
for file in files:
|
||||
basename = os.path.basename(file)
|
||||
# if basename.find('frameId')<0: continue
|
||||
|
||||
|
||||
f, ext = os.path.splitext(basename)
|
||||
_, camer, tamp = f.split('_')
|
||||
|
||||
if camer == '0':
|
||||
tamps_0.append(int(tamp))
|
||||
files_0.append(file)
|
||||
|
||||
if camer == '1':
|
||||
tamps_1.append(int(tamp))
|
||||
files_1.append(file)
|
||||
|
||||
idx0 = sorted(range(len(tamps_0)), key=lambda k: tamps_0[k])
|
||||
files0 = [files_0[i] for i in idx0]
|
||||
|
||||
idx1 = sorted(range(len(tamps_1)), key=lambda k: tamps_1[k])
|
||||
files1 = [files_1[i] for i in idx1]
|
||||
|
||||
|
||||
return (files0, files1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def rename(filePath, tmin):
|
||||
"""
|
||||
重命名函数fun1
|
||||
输入:文件夹路径
|
||||
功能:对文件夹中的全部文件进行随机命名
|
||||
"""
|
||||
suffix = '.png' # 设置后缀,筛选特定文件以更改名称
|
||||
for file in os.listdir(filePath):
|
||||
if file.endswith(suffix):
|
||||
name = file.split('.')[0]
|
||||
|
||||
tamp = int(name.split('_')[2])-tmin
|
||||
|
||||
suffix = file.split('.')[1]
|
||||
|
||||
newname = name +f'_{int(tamp)}.'+suffix
|
||||
|
||||
os.rename(os.path.join(filePath, file), os.path.join(filePath, newname))
|
||||
|
||||
|
||||
def rerename(filePath=None):
|
||||
"""
|
||||
重命名函数fun1
|
||||
输入:文件夹路径
|
||||
功能:对文件夹中的全部文件进行随机命名
|
||||
"""
|
||||
|
||||
suffix = '.png' # 设置后缀,筛选特定文件以更改名称
|
||||
for file in os.listdir(filePath):
|
||||
if file.endswith(suffix):
|
||||
name = file.split('.')[0]
|
||||
names = name.split('_')
|
||||
if len(names)>=6:
|
||||
newname = "_".join(names[0:5])+'.png'
|
||||
os.rename(os.path.join(filePath, file), os.path.join(filePath, newname))
|
||||
|
||||
|
||||
def state_measure(periods, weights, spath=None):
|
||||
'''
|
||||
数据类型
|
||||
后摄: 0, 前摄: 1, CV综合: 2, 重力: 9
|
||||
frstate_0/1:
|
||||
帧ID 时间戳 单摄状态1 单摄状态2 活动轨迹标记
|
||||
0 1 2 3 4:end
|
||||
|
||||
|
||||
|
||||
time_stream = np.concatenate((tstream, weights))
|
||||
time_stream:
|
||||
序列索引号 数据类型 时间戳 单摄状态1/重力值 单摄状态2/重力(t0, t1) CV状态/重力(t0', t1') 综合数据类型 综合状态
|
||||
0 1 2 3 4 5 6 7
|
||||
|
||||
单摄状态1:基于运动轨迹的起止点确定的运动区间
|
||||
单摄状态2: 基于滑动窗口的起止点确定的运动区间
|
||||
重力(t0, t1): 重力波动的精确时间区间,基于重力波动的起止点,而不是仅依赖重力稳定时间
|
||||
重力(t0', t1'): 根据加退购对重力波动窗口进行扩展,扩展应该涵盖购物事件的发生过程
|
||||
方案:
|
||||
前后摄状态进行或运算
|
||||
CV与重力状态进行与运算
|
||||
'''
|
||||
|
||||
# BackType = 0 # 后摄数据类型
|
||||
# FrontType = 1 # 前摄数据类型
|
||||
CameraType = 2 # CV数据综合类型
|
||||
WeightType = 9 # 重力数据类型
|
||||
WeightStableThresh = 7.5 # 单位:g,重力稳定状态下的最大波动范围
|
||||
WeightWinWidth = 10 # 单位:重力数据点数,该值和采样间隔关联,重力稳定时间设定为500ms = WeightWinWidth * 采样间隔
|
||||
CameraTimeInterval = 100 # 单位:ms,前后摄状态进行或运算时的时间间隔阈值
|
||||
InputFrontNum = 10 # 重力增加(放入)向前延拓的重力数据点数
|
||||
InputBackNum = 0 # 重力增加(放入)向后延拓的重力数据点数
|
||||
OutputFrontNum = 2 # 重力减少(取出)向前延拓的重力数据点数
|
||||
OutputBackNum = 10 # 重力减少(取出)向前延拓的重力数据点数
|
||||
CompTimeInterval = 150 # 单位:ms,CV状态和重力状态进行与运算时的时间间隔阈值
|
||||
|
||||
|
||||
'''==================== 1.1 Weight 数据综合并排序 ======================='''
|
||||
nw = len(weights)
|
||||
widx = np.array([k for k in range(0, nw)])[:, None]
|
||||
wtype = WeightType * np.ones((nw, 1))
|
||||
wstate = np.zeros((nw, 4))
|
||||
weights = np.concatenate((widx, wtype, weights, wstate), axis=1).astype(np.int64)
|
||||
weights[:, 6] = WeightType
|
||||
|
||||
weights = weights[np.argsort(weights[:, 2]), :]
|
||||
|
||||
'''=================== 1.2 基确Weight的状态切割 ========================='''
|
||||
w_max = np.max(weights[:, 3])
|
||||
# i0=0
|
||||
for i2 in range(0, nw):
|
||||
i1 = max(i2 - WeightWinWidth, 0)
|
||||
wvalue = weights[i1:i2+1, 3]
|
||||
wi2 = weights[i2, 3]
|
||||
wmin = np.min(wvalue)
|
||||
wmax = np.max(wvalue)
|
||||
|
||||
|
||||
'''对重力波动区间进行标记,并标记最新一次重力稳定值的索引和相应重力值'''
|
||||
if wmax - wmin > WeightStableThresh:
|
||||
weights[i2, 4] = w_max
|
||||
elif i2==0:
|
||||
i0=0
|
||||
wi0 = weights[i0, 3]
|
||||
elif i2>0 and weights[i2-1, 4]==0:
|
||||
i0 = copy.deepcopy(i2)
|
||||
wi0 = weights[i0, 3]
|
||||
|
||||
|
||||
if i2>0 and weights[i2-1, 4]!=0 and weights[i2, 4]==0:
|
||||
# 当前稳定状态下的重力值和前一次重力稳定值的差值,确定放入还是取出
|
||||
if wi2-wi0 > WeightStableThresh:
|
||||
i00 = max(i0 - InputFrontNum, 0)
|
||||
i22 = min(i2 + InputBackNum, nw)
|
||||
elif wi2-wi0 < -1*WeightStableThresh:
|
||||
i00 = max(i0 - OutputFrontNum, 0)
|
||||
i22 = min(i2 + OutputBackNum, nw)
|
||||
else:
|
||||
i00 = max(i0 - max(InputFrontNum, OutputFrontNum), 0)
|
||||
i22 = min(i2 + max(InputBackNum, OutputBackNum), nw)
|
||||
|
||||
weights[i00:i22, 5] = w_max + 100
|
||||
|
||||
|
||||
'''===================== 2.1 CV 数据综合并排序 =========================='''
|
||||
BackType, frstate_0 = periods[0]
|
||||
FrontType, frstate_1 = periods[1]
|
||||
|
||||
|
||||
n0, n1 = len(frstate_0), len(frstate_1)
|
||||
idx0 = np.array([i for i in range(0, n0)], dtype=np.int64)[:, None]
|
||||
idx1 = np.array([i for i in range(0, n1)], dtype=np.int64)[:, None]
|
||||
ctype0 = BackType * np.ones((n0, 1), dtype=np.int64)
|
||||
ctype1 = FrontType * np.ones((n1, 1), dtype=np.int64)
|
||||
tstamp0 = frstate_0[:,1][:, None]
|
||||
tstamp1 = frstate_1[:,1][:, None]
|
||||
state0 = frstate_0[:,2][:, None]
|
||||
state00 = frstate_0[:,3][:, None]
|
||||
|
||||
state1 = frstate_1[:,2][:, None]
|
||||
state11 = frstate_1[:,3][:, None]
|
||||
|
||||
|
||||
|
||||
|
||||
'''序列索引号, 相机类型,时间戳, 单摄状态1、单摄状态2、CV综合状态、综合数据类型、综合状态
|
||||
0 1 2 3 4 5 6 7
|
||||
'''
|
||||
tstream0 = np.concatenate((idx0, ctype0, tstamp0, state0, state00), axis=1)
|
||||
tstream1 = np.concatenate((idx1, ctype1, tstamp1, state1, state11), axis=1)
|
||||
tstream = np.concatenate((tstream0, tstream1), axis=0)
|
||||
tstream = np.concatenate((tstream, np.zeros((len(tstream), 3), dtype=np.int64)), axis=1)
|
||||
tstream[:, 6] = CameraType
|
||||
tstream = tstream[np.argsort(tstream[:, 2]), :]
|
||||
|
||||
'''=============== 2.2 基于前后摄运动轨迹起止点确定CV综合状态 ============'''
|
||||
for i in range(0, len(tstream)):
|
||||
idx, ctype, stamp, state = tstream[i, :4]
|
||||
if i==0:
|
||||
tstream[i, 5] = state
|
||||
if i>0:
|
||||
j = i-1
|
||||
idx0, ctype0, stamp0, state0 = tstream[j, :4]
|
||||
while stamp-stamp0 < CameraTimeInterval and ctype == ctype0 and j>0:
|
||||
j -= 1
|
||||
idx0, ctype0, stamp0, state0 = tstream[j, :4]
|
||||
|
||||
'''两摄像头状态的或运算. 由于前后摄图像不同时,如何构造或运算,关键在于选择不同摄像头的对齐点
|
||||
i时刻摄像头(ctype)状态state,另一摄像头(ctype0 != ctype)距 i 最近最近时刻 j 的状态state0
|
||||
'''
|
||||
if ctype != ctype0 and state0==1:
|
||||
tstream[i, 5] = state0
|
||||
else:
|
||||
tstream[i, 5] = state
|
||||
|
||||
|
||||
'''================ 3.1 CV、Wweight 数据综合并排序 ======================'''
|
||||
time_stream = np.concatenate((tstream, weights), axis=0, dtype=np.int64)
|
||||
time_stream = time_stream[np.argsort(time_stream[:, 2]), :]
|
||||
tmin = np.min(time_stream[:, 2])
|
||||
time_stream[:, 2] = time_stream[:, 2] - tmin
|
||||
|
||||
'''============== 3.2 基于 CV 和 Weight 确定 Cart 的综合状态 ============'''
|
||||
for i in range(0, len(time_stream)):
|
||||
idx, _, stamp, value, _, state, ctype = time_stream[i, :7]
|
||||
state = min(state, 1)
|
||||
|
||||
if i==0:
|
||||
time_stream[i, 7] = state
|
||||
|
||||
if i>0:
|
||||
j = i-1
|
||||
idx0, _, stamp0, value0, _, state0, ctype0 = time_stream[j, :7]
|
||||
while stamp-stamp0 < CompTimeInterval and ctype == ctype0 and j>0:
|
||||
j -= 1
|
||||
idx0, _, stamp0, value0, _, state0, ctype0 = time_stream[j, :7]
|
||||
|
||||
'''CV与Weight的与运算. 由于CV与Weight不同时,如何构造与运算,关键在于选择不同数据源的对齐点
|
||||
i时数据类型(ctype)状态state,另一数据类型(ctype0 != ctype)距 i 最近最近时刻 j 的状态state0
|
||||
'''
|
||||
if ctype != ctype0 and state !=0 and state0 !=0:
|
||||
time_stream[i, 7] = 1
|
||||
|
||||
MotionSlice = []
|
||||
|
||||
motion_slice = []
|
||||
|
||||
t0 = time_stream[0, 7]
|
||||
for i in range(1, len(time_stream)):
|
||||
f0 = time_stream[i-1, 7]
|
||||
f1 = time_stream[i, 7]
|
||||
if f0==0 and f1==1:
|
||||
t0 = time_stream[i, 2]
|
||||
elif f0==1 and f1==0:
|
||||
t1 = time_stream[i, 2]
|
||||
if t1-t0>100: #ms
|
||||
MotionSlice.append((t0+tmin, t1+tmin))
|
||||
motion_slice.append((t0, t1))
|
||||
else:
|
||||
print(f"T0: {t0}, T1: {t1}")
|
||||
|
||||
|
||||
'''========================== 4 结果显示 ================================'''
|
||||
frstate_0[:, 1] = frstate_0[:, 1]-tmin
|
||||
frstate_1[:, 1] = frstate_1[:, 1]-tmin
|
||||
tstream[:, 2] = tstream[:, 2]-tmin
|
||||
|
||||
fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 1)
|
||||
during = np.max(time_stream[:, 2])
|
||||
|
||||
ax1.plot(weights[:, 2]-tmin, weights[:, 3], 'bo-', linewidth=1, markersize=4)
|
||||
ax1.plot(weights[:, 2]-tmin, weights[:, 4], 'mx-', linewidth=1, markersize=4)
|
||||
ax1.plot(weights[:, 2]-tmin, weights[:, 5], 'gx-', linewidth=1, markersize=4)
|
||||
ax1.set_xlim([0, during])
|
||||
ax1.set_title('Weight (gram)')
|
||||
|
||||
ax2.plot(frstate_0[:, 1], frstate_0[:, 3], 'rx-', linewidth=1, markersize=8)
|
||||
ax2.plot(frstate_0[:, 1], frstate_0[:, 2], 'bo-', linewidth=1, markersize=4)
|
||||
ax2.set_xlim([0, during])
|
||||
ax2.set_title('Back Camera')
|
||||
|
||||
ax3.plot(frstate_1[:, 1], frstate_1[:, 3], 'rx-', linewidth=1, markersize=8)
|
||||
ax3.plot(frstate_1[:, 1], frstate_1[:, 2], 'bo-', linewidth=1, markersize=4)
|
||||
ax3.set_xlim([0, during])
|
||||
ax3.set_title('Front Camera')
|
||||
|
||||
ax4.plot(tstream[:, 2], tstream[:, 5], 'bx-', linewidth=1, markersize=4)
|
||||
ax4.set_xlim([0, during])
|
||||
ax4.set_title('CV State')
|
||||
|
||||
ax5.plot(time_stream[:, 2], time_stream[:, 7], 'gx-', linewidth=1, markersize=4)
|
||||
ax5.set_xlim([0, during])
|
||||
ax5.set_title('Cart State')
|
||||
|
||||
plt.show()
|
||||
if spath:
|
||||
plt.savefig(spath)
|
||||
|
||||
return tmin, MotionSlice
|
||||
|
||||
def splitevent(imgpath, MotionSlice):
|
||||
suffix = '.png'
|
||||
|
||||
imgfiles = [f for f in os.listdir(imgpath) if f.endswith(suffix)]
|
||||
timestamp = np.array([int(f.split('_')[2]) for f in imgfiles])
|
||||
|
||||
indexes = []
|
||||
k = 0
|
||||
for t0, t1 in MotionSlice:
|
||||
idx0 = set(np.where(timestamp >= t0)[0])
|
||||
idx1 = set(np.where(timestamp <= t1)[0])
|
||||
idx2 = list(idx0.intersection(idx1))
|
||||
files = [imgfiles[i] for i in idx2]
|
||||
|
||||
for filename in files:
|
||||
file, ext = os.path.splitext(filename)
|
||||
newname = file + f'_{k}.png'
|
||||
os.rename(os.path.join(imgpath, filename), os.path.join(imgpath, newname))
|
||||
k += 1
|
||||
|
||||
print("Done!")
|
||||
|
||||
|
||||
|
||||
def runyolo():
|
||||
eventdirs = r"\\192.168.1.28\share\realtime\eventdata"
|
||||
savedir = r"\\192.168.1.28\share\realtime\result"
|
||||
|
||||
for edir in os.listdir(eventdirs):
|
||||
source = os.path.join(eventdirs, edir)
|
||||
files = filesort(source)
|
||||
for flist in files:
|
||||
run_yolo(flist, savedir)
|
||||
|
||||
def run_tracking(trackboxes, MotionSlice):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def show_seri():
|
||||
datapath = r"\\192.168.1.28\share\realtime\eventdata\1728978106733"
|
||||
savedir = r"\\192.168.1.28\share\realtime\result"
|
||||
|
||||
|
||||
imgdir = datapath.split('\\')[-2] + "_" + datapath.split('\\')[-1]
|
||||
imgpath = os.path.join(savedir, imgdir)
|
||||
|
||||
eventname = Path(datapath).stem
|
||||
|
||||
datafiles = sorted(glob.glob(os.path.join(datapath, '*.npy')))
|
||||
|
||||
periods, trackboxes = [], []
|
||||
win_width = 12
|
||||
for npypath in datafiles:
|
||||
CameraType = Path(npypath).stem.split('_')[-1]
|
||||
tkboxes = np.load(npypath)
|
||||
|
||||
trackboxes.append((CameraType, tkboxes))
|
||||
|
||||
period = devide_motion_state(tkboxes, win_width)
|
||||
periods.append((int(CameraType), period))
|
||||
|
||||
|
||||
|
||||
'''===============读取重力信号数据==================='''
|
||||
seneorfile = os.path.join(datapath, 'sensor.txt')
|
||||
WeightDict = read_seneor(seneorfile)
|
||||
|
||||
weights = [(float(t), w) for t, w in WeightDict.items()]
|
||||
weights = np.array(weights)
|
||||
|
||||
|
||||
'''===============重力、图像信息融合==================='''
|
||||
spath = os.path.join(savedir, f"{eventname}.png" )
|
||||
tmin, MotionSlice = state_measure(periods, weights, spath)
|
||||
|
||||
|
||||
|
||||
|
||||
# 第一次运行时用于更改图像文件名
|
||||
# rerename(imgpath)
|
||||
# rename(imgpath, tmin)
|
||||
|
||||
|
||||
# splitevent(imgpath, MotionSlice)
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
# runyolo()
|
||||
|
||||
show_seri()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# imgpaths = r"\\192.168.1.28\share\realtime\result\eventdata_1728978106733"
|
||||
# rerename(imgpaths)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -150,6 +150,8 @@ def yolo_resnet_tracker(
|
||||
save_crop=False, # save cropped prediction boxes
|
||||
|
||||
nosave=False, # do not save images/videos
|
||||
is_save_img = False,
|
||||
is_save_video = True,
|
||||
|
||||
|
||||
classes=None, # filter by class: --class 0, or --class 0 2 3
|
||||
@ -166,9 +168,7 @@ def yolo_resnet_tracker(
|
||||
vid_stride=1, # video frame-rate stride
|
||||
data=ROOT / 'data/coco128.yaml', # dataset.yaml path
|
||||
):
|
||||
source = str(source)
|
||||
save_img = not nosave and not source.endswith('.txt') # save inference images
|
||||
|
||||
# source = str(source)
|
||||
# Load model
|
||||
device = select_device(device)
|
||||
model = DetectMultiBackend(weights, device=device, dnn=dnn, data=data, fp16=half)
|
||||
@ -209,7 +209,6 @@ def yolo_resnet_tracker(
|
||||
for i, det in enumerate(pred): # per image
|
||||
im0 = im0s.copy()
|
||||
|
||||
save_path = str(save_dir / Path(path).name) # im.jpg
|
||||
s += '%gx%g ' % im.shape[2:] # print string
|
||||
|
||||
annotator = Annotator(im0.copy(), line_width=line_thickness, example=str(names))
|
||||
@ -228,7 +227,14 @@ def yolo_resnet_tracker(
|
||||
tracks = tracker.update(det_tracking, im0)
|
||||
if len(tracks) == 0:
|
||||
continue
|
||||
tracks[:, 7] = dataset.frame
|
||||
|
||||
if dataset.mode == "video":
|
||||
frameId = dataset.frame
|
||||
else:
|
||||
frameId = dataset.count
|
||||
|
||||
tracks[:, 7] = frameId
|
||||
|
||||
|
||||
'''================== 1. 存储 dets/subimgs/features Dict ============='''
|
||||
imgs, features = inference_image(im0, tracks)
|
||||
@ -242,7 +248,7 @@ def yolo_resnet_tracker(
|
||||
imgdict.update({int(bid): imgs[ii]}) # [f"img_{int(bid)}"] = imgs[i]
|
||||
boxdict.update({int(bid): tracks[ii, :]}) # [f"box_{int(bid)}"] = tracks[i, :]
|
||||
featdict.update({int(bid): features[ii, :]}) # [f"feat_{int(bid)}"] = features[i, :]
|
||||
TracksDict[f"frame_{int(dataset.frame)}"] = {"imgs":imgdict, "boxes":boxdict, "feats":featdict}
|
||||
TracksDict[f"frame_{int(frameId)}"] = {"imgs":imgdict, "boxes":boxdict, "feats":featdict}
|
||||
|
||||
track_boxes = np.concatenate([track_boxes, tracks], axis=0)
|
||||
|
||||
@ -257,19 +263,20 @@ def yolo_resnet_tracker(
|
||||
color = colors(int(id), True)
|
||||
else:
|
||||
color = colors(19, True) # 19为调色板的最后一个元素
|
||||
|
||||
annotator.box_label(xyxy, label, color=color)
|
||||
|
||||
# Save results (image and video with tracking)
|
||||
'''====== Save results (image and video) ======'''
|
||||
save_path = str(save_dir / Path(path).name) # 带有后缀名
|
||||
im0 = annotator.result()
|
||||
if is_save_img:
|
||||
save_path_img, ext = os.path.splitext(save_path)
|
||||
if save_img:
|
||||
# if dataset.mode == 'image':
|
||||
# imgpath = save_path_img + f"_{dataset}.png"
|
||||
# else:
|
||||
# imgpath = save_path_img + f"_{dataset.frame}.png"
|
||||
# cv2.imwrite(Path(imgpath), im0)
|
||||
if dataset.mode == 'image':
|
||||
imgpath = save_path_img + ".png"
|
||||
else:
|
||||
imgpath = save_path_img + f"_{frameId}.png"
|
||||
cv2.imwrite(Path(imgpath), im0)
|
||||
|
||||
if dataset.mode == 'video' and is_save_video:
|
||||
if vid_path[i] != save_path: # new video
|
||||
vid_path[i] = save_path
|
||||
if isinstance(vid_writer[i], cv2.VideoWriter):
|
||||
@ -396,8 +403,8 @@ def run(
|
||||
imgshow = im0s.copy()
|
||||
|
||||
## ============================= tracking 功能只处理视频,writed by WQG
|
||||
if dataset.mode == 'image':
|
||||
continue
|
||||
# if dataset.mode == 'image':
|
||||
# continue
|
||||
|
||||
with dt[0]:
|
||||
im = torch.from_numpy(im).to(model.device)
|
||||
@ -482,7 +489,14 @@ def run(
|
||||
tracks = tracker.update(det_tracking, im0)
|
||||
if len(tracks) == 0:
|
||||
continue
|
||||
tracks[:, 7] = dataset.frame
|
||||
|
||||
if dataset.mode == "video":
|
||||
frameId = dataset.frame
|
||||
else:
|
||||
frameId = dataset.count
|
||||
tracks[:, 7] = frameId
|
||||
|
||||
tracks[:, 7] = frameId
|
||||
|
||||
'''================== 1. 存储 dets/subimgs/features Dict ============='''
|
||||
imgs, features = inference_image(im0, tracks)
|
||||
@ -496,7 +510,7 @@ def run(
|
||||
imgdict.update({int(bid): imgs[ii]}) # [f"img_{int(bid)}"] = imgs[i]
|
||||
boxdict.update({int(bid): tracks[ii, :]}) # [f"box_{int(bid)}"] = tracks[i, :]
|
||||
featdict.update({int(bid): features[ii, :]}) # [f"feat_{int(bid)}"] = features[i, :]
|
||||
TracksDict[f"frame_{int(dataset.frame)}"] = {"imgs":imgdict, "boxes":boxdict, "feats":featdict}
|
||||
TracksDict[f"frame_{int(frameId)}"] = {"imgs":imgdict, "boxes":boxdict, "feats":featdict}
|
||||
|
||||
track_boxes = np.concatenate([track_boxes, tracks], axis=0)
|
||||
|
||||
@ -535,7 +549,7 @@ def run(
|
||||
if dataset.mode == 'image':
|
||||
imgpath = save_path_img + f"_{dataset}.png"
|
||||
else:
|
||||
imgpath = save_path_img + f"_{dataset.frame}.png"
|
||||
imgpath = save_path_img + f"_{frameId}.png"
|
||||
|
||||
cv2.imwrite(Path(imgpath), im0)
|
||||
|
||||
@ -664,24 +678,38 @@ print('=======')
|
||||
|
||||
def main(opt):
|
||||
check_requirements(ROOT / 'requirements.txt', exclude=('tensorboard', 'thop'))
|
||||
|
||||
p = r"D:\datasets\ym\永辉测试数据_202404\20240402"
|
||||
|
||||
optdict = vars(opt)
|
||||
|
||||
p = r"D:\datasets\ym"
|
||||
p = r"D:\datasets\ym\exhibition\153112511_0_seek_105.mp4"
|
||||
|
||||
files = []
|
||||
k = 0
|
||||
if os.path.isdir(p):
|
||||
files.extend(sorted(glob.glob(os.path.join(p, '*.*'))))
|
||||
for file in files:
|
||||
|
||||
optdict["source"] = file
|
||||
run(**optdict)
|
||||
|
||||
k += 1
|
||||
if k == 2:
|
||||
if k == 1:
|
||||
break
|
||||
elif os.path.isfile(p):
|
||||
optdict["source"] = p
|
||||
run(**vars(opt))
|
||||
|
||||
def main_imgdir(opt):
|
||||
check_requirements(ROOT / 'requirements.txt', exclude=('tensorboard', 'thop'))
|
||||
optdict = vars(opt)
|
||||
|
||||
|
||||
optdict["project"] = r"\\192.168.1.28\share\realtime"
|
||||
|
||||
optdict["source"] = r"\\192.168.1.28\share\realtime\addReturn\add\1728978052624"
|
||||
run(**optdict)
|
||||
|
||||
|
||||
def main_loop(opt):
|
||||
check_requirements(ROOT / 'requirements.txt', exclude=('tensorboard', 'thop'))
|
||||
|
||||
@ -725,8 +753,9 @@ def main_loop(opt):
|
||||
if __name__ == '__main__':
|
||||
opt = parse_opt()
|
||||
|
||||
# main(opt)
|
||||
main_loop(opt)
|
||||
main(opt)
|
||||
# main_imgdir(opt)
|
||||
# main_loop(opt)
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -59,21 +59,21 @@ class ShoppingCart:
|
||||
|
||||
@property
|
||||
def incart(self):
|
||||
img = cv2.imread(str(curpath/'cart_tempt/back_incart.png'), cv2.IMREAD_GRAYSCALE)
|
||||
img = cv2.imread(str(parpath/'shopcart/cart_tempt/incart.png'), cv2.IMREAD_GRAYSCALE)
|
||||
ret, binary = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY)
|
||||
|
||||
return binary
|
||||
|
||||
@property
|
||||
def outcart(self):
|
||||
img = cv2.imread(str(curpath/'cart_tempt/back_outcart.png'), cv2.IMREAD_GRAYSCALE)
|
||||
img = cv2.imread(str(parpath/'shopcart/cart_tempt/outcart.png'), cv2.IMREAD_GRAYSCALE)
|
||||
ret, binary = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY)
|
||||
|
||||
return binary
|
||||
|
||||
@property
|
||||
def cartedge(self):
|
||||
img = cv2.imread(str(curpath/'cart_tempt/back_cartedge.png'), cv2.IMREAD_GRAYSCALE)
|
||||
img = cv2.imread(str(parpath/'shopcart/cart_tempt/cartedge.png'), cv2.IMREAD_GRAYSCALE)
|
||||
ret, binary = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY)
|
||||
|
||||
return binary
|
||||
@ -521,7 +521,6 @@ class doTracks:
|
||||
|
||||
return mergedTracks
|
||||
|
||||
|
||||
@staticmethod
|
||||
def join_tracks(tlista, tlistb):
|
||||
"""Combine two lists of stracks into a single one."""
|
||||
@ -541,6 +540,93 @@ class doTracks:
|
||||
def sub_tracks(tlista, tlistb):
|
||||
track_ids_b = {t.tid for t in tlistb}
|
||||
return [t for t in tlista if t.tid not in track_ids_b]
|
||||
|
||||
|
||||
|
||||
def array2frame(self, bboxes):
|
||||
frameID = np.sort(np.unique(bboxes[:, 7].astype(int)))
|
||||
fboxes = []
|
||||
for fid in frameID:
|
||||
idx = np.where(bboxes[:, 7] == fid)[0]
|
||||
box = bboxes[idx, :]
|
||||
fboxes.append(box)
|
||||
return fboxes
|
||||
|
||||
|
||||
def isintrude(self):
|
||||
'''
|
||||
boxes: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]
|
||||
0 1 2 3 4 5 6 7 8
|
||||
'''
|
||||
OverlapNum = 3
|
||||
bboxes = self.bboxes.astype(np.int64)
|
||||
fboxes = self.array2frame(bboxes)
|
||||
|
||||
incart = cv2.bitwise_not(self.incart)
|
||||
sum_incart = np.zeros(incart.shape, dtype=np.int64)
|
||||
for fid, boxes in enumerate(fboxes):
|
||||
for i in range(len(boxes)):
|
||||
x1, y1, x2, y2 = boxes[i, 0:4]
|
||||
sum_incart[y1:y2, x1:x2] += 1
|
||||
|
||||
sumincart = np.zeros(sum_incart.shape, dtype=np.uint8)
|
||||
idx255 = np.where(sum_incart >= OverlapNum)
|
||||
sumincart[idx255] = 255
|
||||
|
||||
idxnzr = np.where(sum_incart!=0)
|
||||
base = np.zeros(sum_incart.shape, dtype=np.uint8)
|
||||
base[idxnzr] = 255
|
||||
|
||||
contours_sum, _ = cv2.findContours(sumincart, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||
contours_base, _ = cv2.findContours(base, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||
|
||||
have_existed, invasion = [], []
|
||||
for k, ct_temp in enumerate(contours_base):
|
||||
tmp1 = np.zeros(sum_incart.shape, dtype=np.uint8)
|
||||
cv2.drawContours(tmp1, [ct_temp], -1, 255, cv2.FILLED)
|
||||
|
||||
# 确定轮廓的包含关系
|
||||
for ct_sum in contours_sum:
|
||||
tmp2 = np.zeros(sum_incart.shape, dtype=np.uint8)
|
||||
cv2.drawContours(tmp2, [ct_sum], -1, 255, cv2.FILLED)
|
||||
tmp = cv2.bitwise_and(tmp1, tmp2)
|
||||
if np.count_nonzero(tmp) == np.count_nonzero(tmp2):
|
||||
have_existed.append(k)
|
||||
|
||||
inIdx = [i for i in range(len(contours_base)) if i not in have_existed]
|
||||
invasion = np.zeros(sum_incart.shape, dtype=np.uint8)
|
||||
|
||||
for i in inIdx:
|
||||
cv2.drawContours(invasion, [contours_base[i]], -1, 255, cv2.FILLED)
|
||||
cv2.imwrite("./result/intrude/invasion.png", invasion)
|
||||
|
||||
|
||||
Intrude = True if len(inIdx)>=1 else False
|
||||
print(f"is intruded: {Intrude}")
|
||||
|
||||
return Intrude
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,8 +5,15 @@ Created on Mon Mar 4 18:36:31 2024
|
||||
@author: ym
|
||||
"""
|
||||
import numpy as np
|
||||
import cv2
|
||||
from tracking.utils.mergetrack import track_equal_track
|
||||
from scipy.spatial.distance import cdist
|
||||
from pathlib import Path
|
||||
curpath = Path(__file__).resolve().parents[0]
|
||||
curpath = Path(curpath)
|
||||
parpath = curpath.parent
|
||||
|
||||
|
||||
from .dotracks import doTracks, ShoppingCart
|
||||
from .track_back import backTrack
|
||||
|
||||
@ -19,9 +26,25 @@ class doBackTracks(doTracks):
|
||||
self.tracks = [backTrack(b, f) for b, f in zip(self.lboxes, self.lfeats)]
|
||||
|
||||
# self.similar_dict = self.similarity()
|
||||
# self.shopcart = ShoppingCart(bboxes)
|
||||
|
||||
self.incart = self.getincart()
|
||||
|
||||
|
||||
def getincart(self):
|
||||
img1 = cv2.imread(str(parpath/'shopcart/cart_tempt/incart.png'), cv2.IMREAD_GRAYSCALE)
|
||||
img2 = cv2.imread(str(parpath/'shopcart/cart_tempt/cartedge.png'), cv2.IMREAD_GRAYSCALE)
|
||||
|
||||
|
||||
ret, binary1 = cv2.threshold(img1, 250, 255, cv2.THRESH_BINARY)
|
||||
ret, binary2 = cv2.threshold(img2, 250, 255, cv2.THRESH_BINARY)
|
||||
|
||||
binary = cv2.bitwise_or(binary1, binary2)
|
||||
|
||||
|
||||
return binary
|
||||
|
||||
|
||||
self.shopcart = ShoppingCart(bboxes)
|
||||
|
||||
def classify(self):
|
||||
'''功能:对 tracks 中元素分类 '''
|
||||
|
@ -4,7 +4,13 @@ Created on Mon Mar 4 18:38:20 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import cv2
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
|
||||
curpath = Path(__file__).resolve().parents[0]
|
||||
curpath = Path(curpath)
|
||||
parpath = curpath.parent
|
||||
# from tracking.utils.mergetrack import track_equal_track
|
||||
from .dotracks import doTracks
|
||||
from .track_front import frontTrack
|
||||
@ -16,6 +22,14 @@ class doFrontTracks(doTracks):
|
||||
# self.tracks = [frontTrack(b) for b in self.lboxes]
|
||||
self.tracks = [frontTrack(b, f) for b, f in zip(self.lboxes, self.lfeats)]
|
||||
|
||||
self.incart = self.getincart()
|
||||
|
||||
def getincart(self):
|
||||
img = cv2.imread(str(parpath/'shopcart/cart_tempt/incart_ftmp.png'), cv2.IMREAD_GRAYSCALE)
|
||||
ret, binary = cv2.threshold(img, 250, 255, cv2.THRESH_BINARY)
|
||||
|
||||
return binary
|
||||
|
||||
|
||||
def classify(self):
|
||||
'''功能:对 tracks 中元素分类 '''
|
||||
|
@ -49,7 +49,7 @@ class backTrack(Track):
|
||||
self.incartrates = incartrates'''
|
||||
self.compute_ious_feat()
|
||||
|
||||
# self.PCA()
|
||||
|
||||
|
||||
|
||||
def isimgborder(self, BoundPixel=10, BoundThresh=0.3):
|
||||
|
@ -5,9 +5,15 @@ Created on Mon Mar 4 18:33:01 2024
|
||||
@author: ym
|
||||
"""
|
||||
import numpy as np
|
||||
from sklearn.cluster import KMeans
|
||||
import cv2
|
||||
# from sklearn.cluster import KMeans
|
||||
from .dotracks import MoveState, Track
|
||||
|
||||
from pathlib import Path
|
||||
curpath = Path(__file__).resolve().parents[0]
|
||||
curpath = Path(curpath)
|
||||
parpath = curpath.parent
|
||||
|
||||
|
||||
class frontTrack(Track):
|
||||
# boxes: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]
|
||||
@ -37,9 +43,6 @@ class frontTrack(Track):
|
||||
self.CART_POSIT_0 = 430
|
||||
self.CART_POSIT_1 = 620
|
||||
|
||||
|
||||
|
||||
|
||||
def is_left_or_right_cornpoint(self):
|
||||
''' 基于 all(boxes),
|
||||
boxes左下角点和图像左下角点重叠 或
|
||||
|
@ -22,9 +22,9 @@ from tracking.dotrack.dotracks_back import doBackTracks
|
||||
from tracking.dotrack.dotracks_front import doFrontTracks
|
||||
from tracking.utils.drawtracks import plot_frameID_y2, draw_all_trajectories
|
||||
|
||||
from tracking.utils.read_data import extract_data, read_deletedBarcode_file, read_tracking_output
|
||||
from tracking.utils.read_data import extract_data, read_deletedBarcode_file, read_tracking_output, read_returnGoods_file
|
||||
|
||||
from contrast_analysis import contrast_analysis
|
||||
from contrast.one2n_contrast import get_relative_paths, one2n_new, read_returnGoods_file
|
||||
from tracking.utils.annotator import TrackAnnotator
|
||||
|
||||
W, H = 1024, 1280
|
||||
@ -32,6 +32,7 @@ Mode = 'front' #'back'
|
||||
ImgFormat = ['.jpg', '.jpeg', '.png', '.bmp']
|
||||
|
||||
|
||||
|
||||
'''调用tracking()函数,利用本地跟踪算法获取各目标轨迹,可以比较本地跟踪算法与现场跟踪算法的区别。'''
|
||||
def init_tracker(tracker_yaml = None, bs=1):
|
||||
"""
|
||||
@ -143,7 +144,7 @@ def do_tracking(fpath, savedir, event_name='images'):
|
||||
# trackerboxes, tracker_feat_dict = tracking(bboxes, ffeats)
|
||||
|
||||
'''1.3 分别构造 2 个文件夹,(1) 存储画框后的图像; (2) 运动轨迹对应的 boxes子图'''
|
||||
save_dir = os.path.join(savedir, event_name)
|
||||
save_dir = os.path.join(savedir, event_name + '_images')
|
||||
subimg_dir = os.path.join(savedir, event_name + '_subimgs')
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
@ -237,14 +238,15 @@ def do_tracking(fpath, savedir, event_name='images'):
|
||||
|
||||
subimg_path = os.path.join(subimg_dir, f'{CamerType}_tid{int(tid)}_{int(fid)}_{int(bid)}.png' )
|
||||
cv2.imwrite(subimg_path, subimg)
|
||||
# for track in tracking_output_boxes:
|
||||
# for *xyxy, tid, conf, cls, fid, bid in track:
|
||||
# img = imgs[int(fid-1)]
|
||||
# x1, y1, x2, y2 = int(xyxy[0]/2), int(xyxy[1]/2), int(xyxy[2]/2), int(xyxy[3]/2)
|
||||
# subimg = img[y1:y2, x1:x2]
|
||||
|
||||
# subimg_path = os.path.join(subimg_dir, f'{CamerType}_tid{int(tid)}_{int(fid-1)}_{int(bid)}_x.png' )
|
||||
# cv2.imwrite(subimg_path, subimg)
|
||||
for track in tracking_output_boxes:
|
||||
for *xyxy, tid, conf, cls, fid, bid in track:
|
||||
img = imgs[int(fid-1)]
|
||||
x1, y1, x2, y2 = int(xyxy[0]/2), int(xyxy[1]/2), int(xyxy[2]/2), int(xyxy[3]/2)
|
||||
subimg = img[y1:y2, x1:x2]
|
||||
|
||||
subimg_path = os.path.join(subimg_dir, f'x_{CamerType}_tid{int(tid)}_{int(fid)}_{int(bid)}.png' )
|
||||
cv2.imwrite(subimg_path, subimg)
|
||||
|
||||
|
||||
return img_tracking, abimg
|
||||
@ -267,9 +269,13 @@ def tracking_simulate(eventpath, savepath):
|
||||
# else:
|
||||
# return
|
||||
# =============================================================================
|
||||
bname = os.path.basename(eventpath)
|
||||
idx = bname.find('2024')
|
||||
enent_name = bname[idx:(idx+15)]
|
||||
enent_name = os.path.basename(eventpath)
|
||||
|
||||
## only for simplify the filename
|
||||
idx = enent_name.find('2024')
|
||||
if idx>=0:
|
||||
enent_name = enent_name[idx:(idx+15)]
|
||||
|
||||
|
||||
'''2. 依次读取 0/1_track.data 中数据,进行仿真'''
|
||||
illu_tracking, illu_select = [], []
|
||||
@ -309,26 +315,33 @@ def tracking_simulate(eventpath, savepath):
|
||||
Img_t = None
|
||||
|
||||
|
||||
'''3.1 单独另存保存完好的 8 轨迹图'''
|
||||
basepath, _ = os.path.split(savepath)
|
||||
trajpath = os.path.join(basepath, 'trajs')
|
||||
if not os.path.exists(trajpath):
|
||||
os.makedirs(trajpath)
|
||||
traj_path = os.path.join(trajpath, enent_name+'.png')
|
||||
|
||||
imgpath_tracking = os.path.join(savepath, enent_name + '_ing.png')
|
||||
imgpath_select = os.path.join(savepath, enent_name + '_slt.png')
|
||||
imgpath_ts = os.path.join(savepath, enent_name + '_ts.png')
|
||||
'''3.1 保存输出轨迹图,若tracking、select的shape相同,则合并输出,否则单独输出'''
|
||||
imgpath_tracking = os.path.join(savepath, enent_name + '_tracking.png')
|
||||
imgpath_select = os.path.join(savepath, enent_name + '_select.png')
|
||||
imgpath_ts = os.path.join(savepath, enent_name + '_tracking_select.png')
|
||||
|
||||
if Img_t is not None and Img_s is not None and np.all(Img_s.shape==Img_t.shape):
|
||||
Img_ts = np.concatenate((Img_t, Img_s), axis = 1)
|
||||
H, W = Img_ts.shape[:2]
|
||||
cv2.line(Img_ts, (int(W/2), 0), (int(W/2), int(H)), (0, 0, 255), 4)
|
||||
cv2.imwrite(imgpath_ts, Img_ts)
|
||||
cv2.imwrite(traj_path, Img_ts)
|
||||
|
||||
else:
|
||||
if Img_s: cv2.imwrite(imgpath_select, Img_s) # 不会执行到该处
|
||||
if Img_t: cv2.imwrite(imgpath_tracking, Img_t) # 不会执行到该处
|
||||
Img_ts = None
|
||||
|
||||
'''3.2 单独另存保存完好的 8 轨迹图'''
|
||||
if Img_ts is not None:
|
||||
basepath, _ = os.path.split(savepath)
|
||||
trajpath = os.path.join(basepath, 'trajs')
|
||||
if not os.path.exists(trajpath):
|
||||
os.makedirs(trajpath)
|
||||
traj_path = os.path.join(trajpath, enent_name+'.png')
|
||||
cv2.imwrite(traj_path, Img_ts)
|
||||
|
||||
|
||||
return Img_ts
|
||||
|
||||
|
||||
|
||||
@ -336,14 +349,30 @@ def tracking_simulate(eventpath, savepath):
|
||||
# warnings.simplefilter("error", category=np.VisibleDeprecationWarning)
|
||||
|
||||
def main_loop():
|
||||
|
||||
|
||||
del_barcode_file = r'\\192.168.1.28\share\测试_202406\0723\0723_3\deletedBarcode.txt'
|
||||
basepath = r'\\192.168.1.28\share\测试_202406\0723\0723_3' # 测试数据文件夹地址
|
||||
SavePath = r'D:\contrast\dataset\resultx' # 结果保存地址
|
||||
# prefix = ["getout_", "input_", "error_"]
|
||||
|
||||
# del_barcode_file = r'\\192.168.1.28\share\测试_202406\1030\images\returnGoods.txt'
|
||||
# basepath = r'\\192.168.1.28\share\测试_202406\1030\images' # 测试数据文件夹地址
|
||||
|
||||
'''获取性能测试数据相关路径'''
|
||||
relative_paths = contrast_analysis(del_barcode_file, basepath, SavePath)
|
||||
SavePath = r'D:\contrast\dataset\resultx' # 结果保存地址
|
||||
saveimgs = True
|
||||
|
||||
if os.path.basename(del_barcode_file).find('deletedBarcode'):
|
||||
relative_paths = get_relative_paths(del_barcode_file, basepath, SavePath, saveimgs)
|
||||
elif os.path.basename(del_barcode_file).find('returnGoods'):
|
||||
blist = read_returnGoods_file(del_barcode_file)
|
||||
errpairs, corrpairs, err_similarity, correct_similarity = one2n_new(blist)
|
||||
relative_paths = []
|
||||
for getoutevent, inputevent, errevent in errpairs:
|
||||
relative_paths.append(os.path.join(basepath, getoutevent))
|
||||
relative_paths.append(os.path.join(basepath, inputevent))
|
||||
relative_paths.append(os.path.join(basepath, errevent))
|
||||
|
||||
# prefix = ["getout_", "input_", "error_"]
|
||||
'''开始循环执行每次测试过任务'''
|
||||
k = 0
|
||||
for tuple_paths in relative_paths:
|
||||
@ -383,12 +412,12 @@ def main():
|
||||
SavePath: 包含二级目录,一级目录为轨迹图像;二级目录为与data文件对应的序列图像存储地址。
|
||||
'''
|
||||
# eventPaths = r'\\192.168.1.28\share\测试_202406\0723\0723_3'
|
||||
eventPaths = r"D:\DetectTracking\tracking\images"
|
||||
|
||||
eventPaths = r'D:\datasets\ym\exhibition\识别错'
|
||||
savePath = r'D:\contrast\dataset\result'
|
||||
|
||||
k=0
|
||||
for pathname in os.listdir(eventPaths):
|
||||
pathname = "20240925-142635-3e3cb61a-8bbe-45f2-aed7-a40de7f2d624_6924743924161"
|
||||
pathname = "放入薯片识别为辣条"
|
||||
|
||||
eventpath = os.path.join(eventPaths, pathname)
|
||||
savepath = os.path.join(savePath, pathname)
|
||||
@ -396,6 +425,7 @@ def main():
|
||||
os.makedirs(savepath)
|
||||
|
||||
tracking_simulate(eventpath, savepath)
|
||||
|
||||
# try:
|
||||
# tracking_simulate(eventpath, savepath)
|
||||
# except Exception as e:
|
||||
|
@ -85,9 +85,7 @@ def have_tracked():
|
||||
k = 0
|
||||
gt = Profile()
|
||||
for filename in os.listdir(trackdict):
|
||||
# filename = 'test_20240402-173935_6920152400975_back_174037372.pkl'
|
||||
# filename = '6907149227609_20240508-174733_back_returnGood_70f754088050_425_17327712807.pkl'
|
||||
# filename = '6907149227609_20240508-174733_front_returnGood_70f754088050_425_17327712807.pkl'
|
||||
filename = '153112511_0_seek_105.pkl'
|
||||
|
||||
file, ext = os.path.splitext(filename)
|
||||
filepath = os.path.join(trackdict, filename)
|
||||
@ -97,6 +95,9 @@ def have_tracked():
|
||||
with gt:
|
||||
if filename.find("front") >= 0:
|
||||
vts = doFrontTracks(bboxes, TracksDict)
|
||||
|
||||
Intrude = vts.isintrude()
|
||||
|
||||
vts.classify()
|
||||
|
||||
save_subimgs(vts, file, TracksDict)
|
||||
@ -113,6 +114,9 @@ def have_tracked():
|
||||
|
||||
else:
|
||||
vts = doBackTracks(bboxes, TracksDict)
|
||||
|
||||
Intrude = vts.isintrude()
|
||||
|
||||
vts.classify()
|
||||
alltracks.append(vts)
|
||||
|
||||
@ -124,9 +128,9 @@ def have_tracked():
|
||||
cv2.imwrite(str(trackpath), img_tracking)
|
||||
print(file+f" need time: {gt.dt:.2f}s")
|
||||
|
||||
# k += 1
|
||||
# if k==1:
|
||||
# break
|
||||
k += 1
|
||||
if k==1:
|
||||
break
|
||||
|
||||
if len(alltracks):
|
||||
drawFeatures(alltracks, save_dir)
|
||||
|
Binary file not shown.
Binary file not shown.
@ -7,11 +7,13 @@ Created on Mon Jan 15 15:26:38 2024
|
||||
import numpy as np
|
||||
import cv2
|
||||
import os
|
||||
from pathlib import Path
|
||||
import matplotlib.pyplot as plt
|
||||
from sklearn.decomposition import PCA
|
||||
from utils.annotator import TrackAnnotator
|
||||
from utils.plotting import colors
|
||||
from pathlib import Path
|
||||
|
||||
from tracking.utils.annotator import TrackAnnotator
|
||||
from tracking.utils.plotting import colors
|
||||
|
||||
|
||||
|
||||
def plot_frameID_y2(vts):
|
||||
|
@ -10,10 +10,10 @@ import numpy as np
|
||||
import re
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
import warnings
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
|
||||
def str_to_float_arr(s):
|
||||
# 移除字符串末尾的逗号(如果存在)
|
||||
if s.endswith(','):
|
||||
@ -31,7 +31,9 @@ def find_samebox_in_array(arr, target):
|
||||
return i
|
||||
return -1
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def extract_data(datapath):
|
||||
@ -41,6 +43,9 @@ def extract_data(datapath):
|
||||
trackerfeats = np.empty((0, 256), dtype=np.float64)
|
||||
|
||||
boxes, feats, tboxes, tfeats = [], [], [], []
|
||||
|
||||
timestamps, frameIds = [], []
|
||||
|
||||
with open(datapath, 'r', encoding='utf-8') as lines:
|
||||
for line in lines:
|
||||
line = line.strip() # 去除行尾的换行符和可能的空白字符
|
||||
@ -50,22 +55,15 @@ def extract_data(datapath):
|
||||
if line.find("CameraId")>=0:
|
||||
if len(boxes): bboxes.append(np.array(boxes))
|
||||
if len(feats): ffeats.append(np.array(feats))
|
||||
|
||||
# with warnings.catch_warnings(record=True) as w:
|
||||
# if len(boxes): bboxes.append(np.array(boxes))
|
||||
# if len(feats): ffeats.append(np.array(feats))
|
||||
# if w:
|
||||
# print(f"捕获到 {len(w)} 个警告:")
|
||||
# for warning in w:
|
||||
# print(f"警告类型: {warning.category}")
|
||||
# print(f"警告消息: {warning.message}")
|
||||
# print(f"警告发生的地方: {warning.filename}:{warning.lineno}")
|
||||
|
||||
if len(tboxes):
|
||||
trackerboxes = np.concatenate((trackerboxes, np.array(tboxes)))
|
||||
if len(tfeats):
|
||||
trackerfeats = np.concatenate((trackerfeats, np.array(tfeats)))
|
||||
|
||||
timestamp, frameId = [int(ln.split(":")[1]) for ln in line.split(",")[1:]]
|
||||
timestamps.append(timestamp)
|
||||
frameIds.append(frameId)
|
||||
|
||||
boxes, feats, tboxes, tfeats = [], [], [], []
|
||||
|
||||
if line.find("box:") >= 0 and line.find("output_box:") < 0:
|
||||
@ -103,6 +101,9 @@ def extract_data(datapath):
|
||||
assert(len(trackerboxes)==len(trackerfeats)), "Error at tracker output!"
|
||||
|
||||
tracker_feat_dict = {}
|
||||
tracker_feat_dict["timestamps"] = timestamps
|
||||
tracker_feat_dict["frameIds"] = frameIds
|
||||
|
||||
for i in range(len(trackerboxes)):
|
||||
tid, fid, bid = int(trackerboxes[i, 4]), int(trackerboxes[i, 7]), int(trackerboxes[i, 8])
|
||||
if f"frame_{fid}" not in tracker_feat_dict:
|
||||
@ -169,8 +170,8 @@ def read_tracking_output(filepath):
|
||||
return np.array(boxes), np.array(feats)
|
||||
|
||||
|
||||
def read_deletedBarcode_file(filePth):
|
||||
with open(filePth, 'r', encoding='utf-8') as f:
|
||||
def read_deletedBarcode_file(filePath):
|
||||
with open(filePath, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
split_flag, all_list = False, []
|
||||
@ -179,6 +180,9 @@ def read_deletedBarcode_file(filePth):
|
||||
clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines]
|
||||
|
||||
for i, line in enumerate(clean_lines):
|
||||
if line.endswith(','):
|
||||
line = line[:-1]
|
||||
|
||||
stripped_line = line.strip()
|
||||
if not stripped_line:
|
||||
if len(barcode_list): dict['barcode'] = barcode_list
|
||||
@ -210,11 +214,106 @@ def read_deletedBarcode_file(filePth):
|
||||
return all_list
|
||||
|
||||
|
||||
def read_returnGoods_file(filePath):
|
||||
'''
|
||||
20241030开始,原 deletedBarcode.txt 中数据格式修改为 returnGoods.txt,读数方式随之变化
|
||||
'''
|
||||
|
||||
with open(filePath, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines]
|
||||
|
||||
|
||||
|
||||
all_list = []
|
||||
split_flag, dict = False, {}
|
||||
barcode_list, similarity_list = [], []
|
||||
event_list, type_list = [], []
|
||||
|
||||
|
||||
for i, line in enumerate(clean_lines):
|
||||
stripped_line = line.strip()
|
||||
if line.endswith(','):
|
||||
line = line[:-1]
|
||||
|
||||
if not stripped_line:
|
||||
if len(barcode_list): dict['barcode'] = barcode_list
|
||||
if len(similarity_list): dict['similarity'] = similarity_list
|
||||
if len(event_list): dict['event'] = event_list
|
||||
if len(type_list): dict['type'] = type_list
|
||||
|
||||
if len(dict) and dict['SeqDir'].find('*')<0:
|
||||
all_list.append(dict)
|
||||
|
||||
split_flag, dict = False, {}
|
||||
barcode_list, similarity_list = [], []
|
||||
event_list, type_list = [], []
|
||||
continue
|
||||
|
||||
if line.find(':')<0: continue
|
||||
if line.find('1:n')==0: continue
|
||||
|
||||
label = line.split(':')[0].strip()
|
||||
value = line.split(':')[1].strip()
|
||||
|
||||
if label == 'SeqDir':
|
||||
dict['SeqDir'] = value
|
||||
dict['Deleted'] = value.split('_')[-1]
|
||||
if label == 'List':
|
||||
split_flag = True
|
||||
continue
|
||||
if split_flag:
|
||||
event_list.append(label)
|
||||
barcode_list.append(label.split('_')[-1])
|
||||
similarity_list.append(value.split(',')[0])
|
||||
type_list.append(value.split('=')[-1])
|
||||
|
||||
if len(barcode_list): dict['barcode'] = barcode_list
|
||||
if len(similarity_list): dict['similarity'] = similarity_list
|
||||
if len(event_list): dict['event'] = event_list
|
||||
if len(type_list): dict['type'] = type_list
|
||||
if len(dict) and dict['SeqDir'].find('*')<0:
|
||||
all_list.append(dict)
|
||||
|
||||
return all_list
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def read_seneor(filepath):
|
||||
WeightDict = OrderedDict()
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
|
||||
keyword = line.split(':')[0]
|
||||
value = line.split(':')[1]
|
||||
|
||||
vdata = [float(s) for s in value.split(',') if len(s)]
|
||||
|
||||
WeightDict[keyword] = vdata[-1]
|
||||
|
||||
return WeightDict
|
||||
|
||||
|
||||
def read_weight_timeConsuming(filePth):
|
||||
WeightDict, SensorDict, ProcessTimeDict = OrderedDict(), OrderedDict(), OrderedDict()
|
||||
|
||||
with open(filePth, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
# label = ''
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
|
||||
|
Binary file not shown.
BIN
utils/__pycache__/getsource.cpython-39.pyc
Normal file
BIN
utils/__pycache__/getsource.cpython-39.pyc
Normal file
Binary file not shown.
@ -257,6 +257,8 @@ class LoadImages:
|
||||
videos = [x for x in files if x.split('.')[-1].lower() in VID_FORMATS]
|
||||
ni, nv = len(images), len(videos)
|
||||
|
||||
|
||||
|
||||
self.img_size = img_size
|
||||
self.stride = stride
|
||||
self.files = images + videos
|
||||
|
60
utils/getsource.py
Normal file
60
utils/getsource.py
Normal file
@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Oct 30 13:18:59 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
||||
IMGFORMATS = '.bmp', '.jpeg', '.jpg', 'png', 'tif', 'tiff', 'webp', 'pfm'
|
||||
VIDFORMATS = '.avi', '.gif', '.m4v', '.mkv', '.mov', '.mp4', '.ts', '.wmv'
|
||||
|
||||
def get_image_pairs(p):
|
||||
files = []
|
||||
files.extend(sorted(glob.glob(os.path.join(p, '*.jpg'))))
|
||||
# images = [x for x in files if x.split('.')[-1].lower() in IMG_FORMATS]
|
||||
|
||||
tamps_0, tamps_1 = [], []
|
||||
files_0, files_1 = [], []
|
||||
for file in files:
|
||||
basename = os.path.basename(file)
|
||||
if basename.find('frameId')<0: continue
|
||||
|
||||
|
||||
f, ext = os.path.splitext(basename)
|
||||
camer, tamp, _, frameId = f.split('_')
|
||||
|
||||
if camer == '0':
|
||||
tamps_0.append(int(tamp))
|
||||
files_0.append(file)
|
||||
|
||||
if camer == '1':
|
||||
tamps_1.append(int(tamp))
|
||||
files_1.append(file)
|
||||
|
||||
idx0 = sorted(range(len(tamps_0)), key=lambda k: tamps_0[k])
|
||||
files0 = [files_0[i] for i in idx0]
|
||||
|
||||
idx1 = sorted(range(len(tamps_1)), key=lambda k: tamps_1[k])
|
||||
files1 = [files_1[i] for i in idx1]
|
||||
|
||||
files = (files0, files1)
|
||||
|
||||
return files
|
||||
|
||||
|
||||
def get_video_pairs(vpath):
|
||||
vdieopath = []
|
||||
for filename in os.listdir(vpath):
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext in VIDFORMATS:
|
||||
vdieopath.append(os.path.join(vpath, filename))
|
||||
return vdieopath
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
60
说明文档.txt
60
说明文档.txt
@ -1,4 +1,4 @@
|
||||
三个功能模块
|
||||
五个功能模块
|
||||
1. Yolo + Tracker + Resnet, 其中 Resnet 的实现在./contrast中
|
||||
track_reid.py
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
3. 比对分析模块,目录为:./contrast
|
||||
2个场景:1:1,1:n
|
||||
1:1场景:
|
||||
(1) OneToOneCompare.txt
|
||||
(1) 利用现场保存数据进行比对
|
||||
OneToOneCompare.txt(现场保存数据)
|
||||
one2one_onsite.py
|
||||
(2) 利用本地算法进行特征提取
|
||||
one2one_contrast.py
|
||||
@ -23,6 +24,29 @@
|
||||
feat_select.py
|
||||
|
||||
|
||||
4. 整体流程仿真
|
||||
pipeline.py
|
||||
SourceType: "image", "video", yolo+resent+tracker模块输入数据类型
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
5. 全实时时间切分仿真分析
|
||||
time_devide.py
|
||||
需分 2 步运行模块:
|
||||
(1) runyolo()
|
||||
|
||||
该模块调用 imgs_inference.py 中模块 run_yolo
|
||||
后续工作:
|
||||
1). 将run_yolo模块与track_redi.yolo_resnet_tracker模块合并
|
||||
2). 图像文件名标准化
|
||||
|
||||
(2) show_seri()
|
||||
该模块调用 event_time_specify.py 中模块 devide_motion_state
|
||||
|
||||
|
||||
具体实现:
|
||||
./tracking
|
||||
tracking_test.py
|
||||
@ -52,15 +76,16 @@
|
||||
(d) 现场算法轨迹选择后的轨迹
|
||||
|
||||
|
||||
|
||||
do_tracking(fpath, savedir, event_name)
|
||||
inputs:
|
||||
fpath: 0/1_track.data文件,并核验是否存在 0/1_tracking_output.data,若不存在该文件,直接返回 None, None
|
||||
|
||||
savedir: 在该文件夹下会建立3个子文件夹及一个png轨迹图
|
||||
./savedir/event_name
|
||||
./savedir/event_name_subimgs
|
||||
./savedir/trajectory
|
||||
./savedir/event_name_ts.png
|
||||
./savedir/event_name_images, 画boxes后的图像序列
|
||||
./savedir/event_name_subimgs, 轨迹分析后的目标子图,无 _x 为PC机结果,有 _x 为平板单摄像头轨迹选择后的输出
|
||||
./savedir/trajectory, 存储每一个轨迹图
|
||||
./savedir/event_name_tracking_select.png 或 enent_name_tracking.png 或 enent_name_select.png
|
||||
|
||||
outputs:
|
||||
img_tracking:本机tracker、tracking 输出的结果比较图
|
||||
@ -127,3 +152,26 @@
|
||||
循环读取不同文件夹中的 deletedBarcode.txt,合并评估。
|
||||
main1():
|
||||
指定deletedBarcode.txt进行1:n性能评估
|
||||
|
||||
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)
|
||||
功能:生成标准特征向量
|
||||
参数:
|
||||
(1) imgpath:图像样本的存储地址
|
||||
(2) bcdpath:对 imgpath 中文件列表进行遍历,形成{barcode: 图像样本地址}形式字典并进行存储
|
||||
(3) featpath:调用 inference_image(), 对每一个barcode,生成字典并进行存储
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user