更新 detacttracking
This commit is contained in:
7
detecttracking/contrast/__init__.py
Normal file
7
detecttracking/contrast/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Sep 26 08:53:58 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
352
detecttracking/contrast/event_test.py
Normal file
352
detecttracking/contrast/event_test.py
Normal file
@ -0,0 +1,352 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Dec 16 18:56:18 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import cv2
|
||||
import json
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import rcParams
|
||||
from matplotlib.font_manager import FontProperties
|
||||
from scipy.spatial.distance import cdist
|
||||
from utils.event import ShoppingEvent, save_data
|
||||
|
||||
|
||||
|
||||
rcParams['font.sans-serif'] = ['SimHei'] # 用黑体显示中文
|
||||
rcParams['axes.unicode_minus'] = False # 正确显示负号
|
||||
|
||||
|
||||
'''*********** USearch ***********'''
|
||||
def read_usearch():
|
||||
stdFeaturePath = r"D:\contrast\stdlib\v11_test.json"
|
||||
stdBarcode = []
|
||||
stdlib = {}
|
||||
with open(stdFeaturePath, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
for dic in data['total']:
|
||||
barcode = dic['key']
|
||||
feature = np.array(dic['value'])
|
||||
stdBarcode.append(barcode)
|
||||
stdlib[barcode] = feature
|
||||
|
||||
return stdlib
|
||||
|
||||
def get_eventlist():
|
||||
'''
|
||||
读取一次测试中的错误事件
|
||||
'''
|
||||
evtpaths = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images"
|
||||
text1 = "one2n_Error.txt"
|
||||
text2 = "one2SN_Error.txt"
|
||||
events = []
|
||||
text = (text1, text2)
|
||||
for txt in text:
|
||||
txtfile = os.path.join(evtpaths, txt)
|
||||
with open(txtfile, "r") as f:
|
||||
lines = f.readlines()
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if line:
|
||||
fpath=os.path.join(evtpaths, line)
|
||||
events.append(fpath)
|
||||
|
||||
events = list(set(events))
|
||||
|
||||
return events
|
||||
|
||||
def single_event():
|
||||
|
||||
events = get_eventlist()
|
||||
|
||||
|
||||
|
||||
'''定义当前事件存储地址及生成相应文件件'''
|
||||
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\single_event"
|
||||
for evtpath in events:
|
||||
event = ShoppingEvent(evtpath)
|
||||
save_data(event, resultPath)
|
||||
|
||||
print(event.evtname)
|
||||
|
||||
|
||||
|
||||
def get_topk_percent(data, k):
|
||||
"""
|
||||
获取数据中最大的 k% 的元素
|
||||
"""
|
||||
# 将数据转换为 NumPy 数组
|
||||
if isinstance(data, list):
|
||||
data = np.array(data)
|
||||
|
||||
percentile = np.percentile(data, 100-k)
|
||||
top_k_percent = data[data >= percentile]
|
||||
|
||||
return top_k_percent
|
||||
def cluster(data, thresh=0.15):
|
||||
# data = np.array([0.1, 0.13, 0.7, 0.2, 0.8, 0.52, 0.3, 0.7, 0.85, 0.58])
|
||||
# data = np.array([0.1, 0.13, 0.2, 0.3])
|
||||
# data = np.array([0.1])
|
||||
|
||||
if isinstance(data, list):
|
||||
data = np.array(data)
|
||||
|
||||
data1 = np.sort(data)
|
||||
cluter, Cluters, = [data1[0]], []
|
||||
for i in range(1, len(data1)):
|
||||
if data1[i] - data1[i-1]< thresh:
|
||||
cluter.append(data1[i])
|
||||
else:
|
||||
Cluters.append(cluter)
|
||||
cluter = [data1[i]]
|
||||
Cluters.append(cluter)
|
||||
|
||||
clt_center = []
|
||||
for clt in Cluters:
|
||||
## 是否应该在此处限制一个聚类中的最小轨迹样本数,应该将该因素放在轨迹分析中
|
||||
# if len(clt)>=3:
|
||||
# clt_center.append(np.mean(clt))
|
||||
clt_center.append(np.mean(clt))
|
||||
|
||||
# print(clt_center)
|
||||
|
||||
return clt_center
|
||||
|
||||
def calc_simil(event, stdfeat):
|
||||
|
||||
def calsiml(feat1, feat2):
|
||||
'''轨迹样本和标准特征集样本相似度的选择策略'''
|
||||
matrix = 1 - cdist(feat1, feat2, 'cosine')
|
||||
simi_max = []
|
||||
for i in range(len(matrix)):
|
||||
sim = np.mean(get_topk_percent(matrix[i, :], 75))
|
||||
simi_max.append(sim)
|
||||
cltc_max = cluster(simi_max)
|
||||
Simi = max(cltc_max)
|
||||
|
||||
## cltc_max为空属于编程考虑不周,应予以排查解决
|
||||
# if len(cltc_max):
|
||||
# Simi = max(cltc_max)
|
||||
# else:
|
||||
# Simi = 0 #不应该走到该处
|
||||
|
||||
|
||||
return Simi
|
||||
|
||||
|
||||
front_boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
front_feats = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容
|
||||
for i in range(len(event.front_boxes)):
|
||||
front_boxes = np.concatenate((front_boxes, event.front_boxes[i]), axis=0)
|
||||
front_feats = np.concatenate((front_feats, event.front_feats[i]), axis=0)
|
||||
|
||||
back_boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
back_feats = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容
|
||||
for i in range(len(event.back_boxes)):
|
||||
back_boxes = np.concatenate((back_boxes, event.back_boxes[i]), axis=0)
|
||||
back_feats = np.concatenate((back_feats, event.back_feats[i]), axis=0)
|
||||
|
||||
if len(front_feats):
|
||||
front_simi = calsiml(front_feats, stdfeat)
|
||||
if len(back_feats):
|
||||
back_simi = calsiml(back_feats, stdfeat)
|
||||
|
||||
'''前后摄相似度融合策略'''
|
||||
if len(front_feats) and len(back_feats):
|
||||
diff_simi = abs(front_simi - back_simi)
|
||||
if diff_simi>0.15:
|
||||
Similar = max([front_simi, back_simi])
|
||||
else:
|
||||
Similar = (front_simi+back_simi)/2
|
||||
elif len(front_feats) and len(back_feats)==0:
|
||||
Similar = front_simi
|
||||
elif len(front_feats)==0 and len(back_feats):
|
||||
Similar = back_simi
|
||||
else:
|
||||
Similar = None # 在event.front_feats和event.back_feats同时为空时
|
||||
|
||||
return Similar
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def simi_matrix():
|
||||
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\single_event"
|
||||
|
||||
stdlib = read_usearch()
|
||||
events = get_eventlist()
|
||||
for evtpath in events:
|
||||
evtname = os.path.basename(evtpath)
|
||||
_, barcode = evtname.split("_")
|
||||
|
||||
# 生成事件与相应标准特征集
|
||||
event = ShoppingEvent(evtpath)
|
||||
stdfeat = stdlib[barcode]
|
||||
|
||||
Similar = calc_simil(event, stdfeat)
|
||||
|
||||
# 构造 boxes 子图存储路径
|
||||
subimgpath = os.path.join(resultPath, f"{event.evtname}", "subimg")
|
||||
if not os.path.exists(subimgpath):
|
||||
os.makedirs(subimgpath)
|
||||
histpath = os.path.join(resultPath, "simi_hist")
|
||||
if not os.path.exists(histpath):
|
||||
os.makedirs(histpath)
|
||||
|
||||
|
||||
|
||||
mean_values, max_values = [], []
|
||||
cameras = ('front', 'back')
|
||||
fig, ax = plt.subplots(2, 3, figsize=(16, 9), dpi=100)
|
||||
kpercent = 25
|
||||
for camera in cameras:
|
||||
boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
evtfeat = np.empty((0, 256), dtype=np.float64) ##和类doTracks兼容
|
||||
if camera == 'front':
|
||||
for i in range(len(event.front_boxes)):
|
||||
boxes = np.concatenate((boxes, event.front_boxes[i]), axis=0)
|
||||
evtfeat = np.concatenate((evtfeat, event.front_feats[i]), axis=0)
|
||||
imgpaths = event.front_imgpaths
|
||||
|
||||
else:
|
||||
for i in range(len(event.back_boxes)):
|
||||
boxes = np.concatenate((boxes, event.back_boxes[i]), axis=0)
|
||||
evtfeat = np.concatenate((evtfeat, event.back_feats[i]), axis=0)
|
||||
imgpaths = event.back_imgpaths
|
||||
|
||||
assert len(boxes)==len(evtfeat), f"Please check the Event: {evtname}"
|
||||
if len(boxes)==0: continue
|
||||
print(evtname)
|
||||
|
||||
matrix = 1 - cdist(evtfeat, stdfeat, 'cosine')
|
||||
simi_1d = matrix.flatten()
|
||||
simi_mean = np.mean(matrix, axis=1)
|
||||
# simi_max = np.max(matrix, axis=1)
|
||||
|
||||
'''以相似度矩阵每一行最大的 k% 的相似度做均值计算'''
|
||||
simi_max = []
|
||||
for i in range(len(matrix)):
|
||||
sim = np.mean(get_topk_percent(matrix[i, :], kpercent))
|
||||
simi_max.append(sim)
|
||||
|
||||
|
||||
mean_values.append(np.mean(matrix))
|
||||
max_values.append(np.mean(simi_max))
|
||||
|
||||
diff_max_mean = np.mean(simi_max) - np.mean(matrix)
|
||||
|
||||
'''相似度统计特性图示'''
|
||||
k =0
|
||||
if camera == 'front': k = 1
|
||||
|
||||
'''********************* 相似度全体数据 *********************'''
|
||||
ax[k, 0].hist(simi_1d, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
ax[k, 0].set_xlim([-0.2, 1])
|
||||
ax[k, 0].set_title(camera)
|
||||
|
||||
_, y_max = ax[k, 0].get_ylim() # 获取y轴范围
|
||||
'''相似度变动范围'''
|
||||
ax[k, 0].text(-0.1, 0.15*y_max, f"rng:{max(simi_1d)-min(simi_1d):.3f}", fontsize=18, color='b')
|
||||
|
||||
'''********************* 均值********************************'''
|
||||
ax[k, 1].hist(simi_mean, bins=24, range=(-0.2, 1), edgecolor='black')
|
||||
ax[k, 1].set_xlim([-0.2, 1])
|
||||
ax[k, 1].set_title("mean")
|
||||
_, y_max = ax[k, 1].get_ylim() # 获取y轴范围
|
||||
'''相似度变动范围'''
|
||||
ax[k, 1].text(-0.1, 0.15*y_max, f"rng:{max(simi_mean)-min(simi_mean):.3f}", fontsize=18, color='b')
|
||||
|
||||
|
||||
'''********************* 最大值 ******************************'''
|
||||
ax[k, 2].hist(simi_max, bins=24, range=(-0.2, 1), edgecolor='black')
|
||||
ax[k, 2].set_xlim([-0.2, 1])
|
||||
ax[k, 2].set_title("max")
|
||||
_, y_max = ax[k, 2].get_ylim() # 获取y轴范围
|
||||
'''相似度变动范围'''
|
||||
ax[k, 2].text(-0.1, 0.15*y_max, f"rng:{max(simi_max)-min(simi_max):.3f}", fontsize=18, color='b')
|
||||
|
||||
|
||||
'''绘制聚类中心'''
|
||||
cltc_mean = cluster(simi_mean)
|
||||
for value in cltc_mean:
|
||||
ax[k, 1].axvline(x=value, color='m', linestyle='--', linewidth=3)
|
||||
|
||||
cltc_max = cluster(simi_max)
|
||||
for value in cltc_max:
|
||||
ax[k, 2].axvline(x=value, color='m', linestyle='--', linewidth=3)
|
||||
|
||||
'''绘制相似度均值与最大值均值'''
|
||||
ax[k, 1].axvline(x=np.mean(matrix), color='r', linestyle='-', linewidth=3)
|
||||
ax[k, 2].axvline(x=np.mean(simi_max), color='g', linestyle='-', linewidth=3)
|
||||
|
||||
'''绘制相似度最大值均值 - 均值'''
|
||||
_, y_max = ax[k, 2].get_ylim() # 获取y轴范围
|
||||
ax[k, 2].text(-0.1, 0.05*y_max, f"g-r={diff_max_mean:.3f}", fontsize=18, color='m')
|
||||
|
||||
plt.show()
|
||||
|
||||
# for i, box in enumerate(boxes):
|
||||
# x1, y1, x2, y2, tid, score, cls, fid, bid = box
|
||||
# imgpath = imgpaths[int(fid-1)]
|
||||
# image = cv2.imread(imgpath)
|
||||
# subimg = image[int(y1/2):int(y2/2), int(x1/2):int(x2/2), :]
|
||||
# camerType, timeTamp, _, frameID = os.path.basename(imgpath).split('.')[0].split('_')
|
||||
# subimgName = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID})_{simi_mean[i]:.3f}.png"
|
||||
# imgpairs.append((subimgName, subimg))
|
||||
# spath = os.path.join(subimgpath, subimgName)
|
||||
# cv2.imwrite(spath, subimg)
|
||||
|
||||
# oldname = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID}).png"
|
||||
# oldpath = os.path.join(subimgpath, oldname)
|
||||
# if os.path.exists(oldpath):
|
||||
# os.remove(oldpath)
|
||||
|
||||
|
||||
if len(mean_values)==2:
|
||||
mean_diff = abs(mean_values[1]-mean_values[0])
|
||||
ax[0, 1].set_title(f"mean diff: {mean_diff:.3f}")
|
||||
if len(max_values)==2:
|
||||
max_values = abs(max_values[1]-max_values[0])
|
||||
ax[0, 2].set_title(f"max diff: {max_values:.3f}")
|
||||
try:
|
||||
fig.suptitle(f"Similar: {Similar:.3f}", fontsize=16)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print(f"Similar: {Similar}")
|
||||
pltpath = os.path.join(subimgpath, f"hist_max_{kpercent}%_.png")
|
||||
plt.savefig(pltpath)
|
||||
|
||||
pltpath1 = os.path.join(histpath, f"{evtname}_.png")
|
||||
plt.savefig(pltpath1)
|
||||
|
||||
|
||||
plt.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
simi_matrix()
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# cluster()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
87
detecttracking/contrast/feat_extract/config.py
Normal file
87
detecttracking/contrast/feat_extract/config.py
Normal file
@ -0,0 +1,87 @@
|
||||
# import torch
|
||||
# import torchvision.transforms as T
|
||||
#
|
||||
#
|
||||
# class Config:
|
||||
# # network settings
|
||||
# backbone = 'resnet18' # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3_small, mobilenetv3_large, mobilenet_v1, PPLCNET_x1_0, PPLCNET_x0_5, PPLCNET_x2_5]
|
||||
# metric = 'arcface' # [cosface, arcface]
|
||||
# cbam = True
|
||||
# embedding_size = 256
|
||||
# drop_ratio = 0.5
|
||||
# img_size = 224
|
||||
#
|
||||
# batch_size = 8
|
||||
#
|
||||
# # data preprocess
|
||||
# # input_shape = [1, 128, 128]
|
||||
# """transforms.RandomCrop(size),
|
||||
# transforms.RandomVerticalFlip(p=0.5),
|
||||
# transforms.RandomHorizontalFlip(),
|
||||
# RandomRotate(15, 0.3),
|
||||
# # RandomGaussianBlur()"""
|
||||
#
|
||||
# train_transform = T.Compose([
|
||||
# T.ToTensor(),
|
||||
# T.Resize((img_size, img_size)),
|
||||
# # T.RandomCrop(img_size),
|
||||
# # T.RandomHorizontalFlip(p=0.5),
|
||||
# T.RandomRotation(180),
|
||||
# T.ColorJitter(brightness=0.5),
|
||||
# T.ConvertImageDtype(torch.float32),
|
||||
# T.Normalize(mean=[0.5], std=[0.5]),
|
||||
# ])
|
||||
# test_transform = T.Compose([
|
||||
# T.ToTensor(),
|
||||
# T.Resize((img_size, img_size)),
|
||||
# T.ConvertImageDtype(torch.float32),
|
||||
# T.Normalize(mean=[0.5], std=[0.5]),
|
||||
# ])
|
||||
#
|
||||
# # dataset
|
||||
# train_root = './data/2250_train/train' # 初始筛选过一次的数据集
|
||||
# # train_root = './data/0612_train/train'
|
||||
# test_root = "./data/2250_train/val/"
|
||||
# # test_root = "./data/0612_train/val"
|
||||
# test_list = "./data/2250_train/val_pair.txt"
|
||||
#
|
||||
# test_group_json = "./2250_train/cross_same_0508.json"
|
||||
#
|
||||
#
|
||||
# # test_list = "./data/test_data_100/val_pair.txt"
|
||||
#
|
||||
# # training settings
|
||||
# checkpoints = "checkpoints/resnet18_0613/" # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3]
|
||||
# restore = False
|
||||
# # restore_model = "checkpoints/renet18_2250_0315/best_resnet18_2250_0315.pth" # best_resnet18_1491_0306.pth
|
||||
# restore_model = "checkpoints/resnet18_0515/best.pth" # best_resnet18_1491_0306.pth
|
||||
#
|
||||
# # test_model = "checkpoints/renet18_2250_0314/best_resnet18_2250_0314.pth"
|
||||
# testbackbone = 'resnet18' # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3_small, mobilenetv3_large, mobilenet_v1, PPLCNET_x1_0, PPLCNET_x0_5]
|
||||
# test_val = "D:/比对/cl"
|
||||
# # test_val = "./data/test_data_100"
|
||||
#
|
||||
# # test_model = "checkpoints/zhanting_res_801.pth"
|
||||
# test_model = "checkpoints/resnet18_0515/v11.pth"
|
||||
#
|
||||
#
|
||||
#
|
||||
# train_batch_size = 512 # 256
|
||||
# test_batch_size = 256 # 256
|
||||
#
|
||||
# epoch = 300
|
||||
# optimizer = 'sgd' # ['sgd', 'adam']
|
||||
# lr = 1.5e-2 # 1e-2
|
||||
# lr_step = 5 # 10
|
||||
# lr_decay = 0.95 # 0.98
|
||||
# weight_decay = 5e-4
|
||||
# loss = 'cross_entropy' # ['focal_loss', 'cross_entropy']
|
||||
# # device = torch.device('cuda:1' if torch.cuda.is_available() else 'cpu')
|
||||
# device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
|
||||
#
|
||||
# pin_memory = True # if memory is large, set it True to speed up a bit
|
||||
# num_workers = 4 # dataloader
|
||||
#
|
||||
# group_test = True
|
||||
#
|
||||
# config = Config()
|
547
detecttracking/contrast/feat_extract/inference.py
Normal file
547
detecttracking/contrast/feat_extract/inference.py
Normal file
@ -0,0 +1,547 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|
||||
@author: LiChen
|
||||
"""
|
||||
import numpy as np
|
||||
import torch
|
||||
from pathlib import Path
|
||||
from utils.config import config as cfg
|
||||
|
||||
curpath = Path(__file__).resolve().parents[0]
|
||||
|
||||
|
||||
class FeatsInterface:
|
||||
def __init__(self, resnetModel=None):
|
||||
self.device = cfg.device
|
||||
self.transform = cfg.test_transform
|
||||
self.batch_size = cfg.batch_size
|
||||
self.embedding_size = cfg.embedding_size
|
||||
assert resnetModel is not None, "resnetModel is None"
|
||||
self.model = resnetModel
|
||||
print(f"Model type: {type(self.model)}")
|
||||
|
||||
def inference(self, images, detections=None):
|
||||
'''
|
||||
如果是BGR,需要转变为RGB格式
|
||||
'''
|
||||
if isinstance(images, np.ndarray):
|
||||
imgs, features = self.inference_image(images, detections)
|
||||
return imgs, features
|
||||
|
||||
batch_patches = []
|
||||
patches = []
|
||||
for i, img in enumerate(images):
|
||||
img = img.copy()
|
||||
patch = self.transform(img)
|
||||
if str(self.device) != "cpu":
|
||||
# patch = patch.to(device=self.device).half()
|
||||
patch = patch.to(device=self.device)
|
||||
else:
|
||||
patch = patch.to(device=self.device)
|
||||
|
||||
patches.append(patch)
|
||||
if (i + 1) % self.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, self.embedding_size))
|
||||
for patches in batch_patches:
|
||||
pred = self.model(patches)
|
||||
pred[torch.isinf(pred)] = 1.0
|
||||
feat = pred.cpu().data.numpy()
|
||||
features = np.vstack((features, feat))
|
||||
return features
|
||||
|
||||
def inference_image(self, image, detections):
|
||||
H, W, _ = np.shape(image)
|
||||
|
||||
batch_patches = []
|
||||
patches = []
|
||||
imgs = []
|
||||
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])
|
||||
img = image[tlbr[1]:tlbr[3], tlbr[0]:tlbr[2], :]
|
||||
|
||||
imgs.append(img)
|
||||
|
||||
img1 = img[:, :, ::-1].copy() # the model expects RGB inputs
|
||||
patch = self.transform(img1)
|
||||
|
||||
# patch = patch.to(device=self.device).half()
|
||||
if str(self.device) != "cpu":
|
||||
# patch = patch.to(device=self.device).half()
|
||||
patch = patch.to(device=self.device)
|
||||
else:
|
||||
patch = patch.to(device=self.device)
|
||||
|
||||
patches.append(patch)
|
||||
if (d + 1) % self.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, self.embedding_size))
|
||||
for patches in batch_patches:
|
||||
pred = self.model(patches)
|
||||
pred[torch.isinf(pred)] = 1.0
|
||||
feat = pred.cpu().data.numpy()
|
||||
features = np.vstack((features, feat))
|
||||
|
||||
return imgs, features
|
||||
|
||||
|
||||
# def unique_image(pair_list) -> set:
|
||||
# """Return unique image path in pair_list.txt"""
|
||||
# with open(pair_list, 'r') as fd:
|
||||
# pairs = fd.readlines()
|
||||
# unique = set()
|
||||
# for pair in pairs:
|
||||
# id1, id2, _ = pair.split()
|
||||
# unique.add(id1)
|
||||
# unique.add(id2)
|
||||
# return unique
|
||||
#
|
||||
#
|
||||
# def group_image(images: set, batch) -> list:
|
||||
# """Group image paths by batch size"""
|
||||
# images = list(images)
|
||||
# size = len(images)
|
||||
# res = []
|
||||
# for i in range(0, size, batch):
|
||||
# end = min(batch + i, size)
|
||||
# res.append(images[i: end])
|
||||
# return res
|
||||
#
|
||||
#
|
||||
# def _preprocess(images: list, transform) -> torch.Tensor:
|
||||
# res = []
|
||||
# for img in images:
|
||||
# im = Image.open(img)
|
||||
# im = transform(im)
|
||||
# res.append(im)
|
||||
# # data = torch.cat(res, dim=0) # shape: (batch, 128, 128)
|
||||
# # data = data[:, None, :, :] # shape: (batch, 1, 128, 128)
|
||||
# data = torch.stack(res)
|
||||
# return data
|
||||
#
|
||||
#
|
||||
# def test_preprocess(images: list, transform) -> torch.Tensor:
|
||||
# res = []
|
||||
# for img in images:
|
||||
# im = Image.open(img)
|
||||
# im = transform(im)
|
||||
# res.append(im)
|
||||
# # data = torch.cat(res, dim=0) # shape: (batch, 128, 128)
|
||||
# # data = data[:, None, :, :] # shape: (batch, 1, 128, 128)
|
||||
# data = torch.stack(res)
|
||||
# return data
|
||||
#
|
||||
#
|
||||
# def featurize(images: list, transform, net, device, train=False) -> dict:
|
||||
# """featurize each image and save into a dictionary
|
||||
# Args:
|
||||
# images: image paths
|
||||
# transform: test transform
|
||||
# net: pretrained model
|
||||
# device: cpu or cuda
|
||||
# Returns:
|
||||
# Dict (key: imagePath, value: feature)
|
||||
# """
|
||||
# if train:
|
||||
# data = _preprocess(images, transform)
|
||||
# data = data.to(device)
|
||||
# net = net.to(device)
|
||||
# with torch.no_grad():
|
||||
# features = net(data)
|
||||
# res = {img: feature for (img, feature) in zip(images, features)}
|
||||
# else:
|
||||
# data = test_preprocess(images, transform)
|
||||
# data = data.to(device)
|
||||
# net = net.to(device)
|
||||
# with torch.no_grad():
|
||||
# features = net(data)
|
||||
# res = {img: feature for (img, feature) in zip(images, features)}
|
||||
# return res
|
||||
#
|
||||
#
|
||||
# # def inference_image(images: list, transform, net, device, bs=16, embedding_size=256) -> dict:
|
||||
# # batch_patches = []
|
||||
# # patches = []
|
||||
# # for d, img in enumerate(images):
|
||||
# # img = Image.open(img)
|
||||
# # patch = transform(img)
|
||||
#
|
||||
# # if str(device) != "cpu":
|
||||
# # patch = patch.to(device).half()
|
||||
# # else:
|
||||
# # patch = patch.to(device)
|
||||
#
|
||||
# # patches.append(patch)
|
||||
# # if (d + 1) % bs == 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, embedding_size), dtype=np.float32)
|
||||
# # for patches in batch_patches:
|
||||
# # pred = net(patches)
|
||||
# # pred[torch.isinf(pred)] = 1.0
|
||||
# # feat = pred.cpu().data.numpy()
|
||||
# # features = np.vstack((features, feat))
|
||||
#
|
||||
#
|
||||
# # return features
|
||||
#
|
||||
#
|
||||
# def featurize_1(images: list, transform, net, device, train=False) -> dict:
|
||||
# """featurize each image and save into a dictionary
|
||||
# Args:
|
||||
# images: image paths
|
||||
# transform: test transform
|
||||
# net: pretrained model
|
||||
# device: cpu or cuda
|
||||
# Returns:
|
||||
# Dict (key: imagePath, value: feature)
|
||||
# """
|
||||
#
|
||||
# data = test_preprocess(images, transform)
|
||||
# data = data.to(device)
|
||||
# net = net.to(device)
|
||||
# with torch.no_grad():
|
||||
# features = net(data).data.numpy()
|
||||
#
|
||||
# return features
|
||||
#
|
||||
#
|
||||
# def cosin_metric(x1, x2):
|
||||
# return np.dot(x1, x2) / (np.linalg.norm(x1) * np.linalg.norm(x2))
|
||||
#
|
||||
#
|
||||
# def threshold_search(y_score, y_true):
|
||||
# y_score = np.asarray(y_score)
|
||||
# y_true = np.asarray(y_true)
|
||||
# best_acc = 0
|
||||
# best_th = 0
|
||||
# for i in range(len(y_score)):
|
||||
# th = y_score[i]
|
||||
# y_test = (y_score >= th)
|
||||
# acc = np.mean((y_test == y_true).astype(int))
|
||||
# if acc > best_acc:
|
||||
# best_acc = acc
|
||||
# best_th = th
|
||||
# return best_acc, best_th
|
||||
#
|
||||
#
|
||||
# def showgrid(recall, recall_TN, PrecisePos, PreciseNeg):
|
||||
# x = np.linspace(start=-1.0, stop=1.0, num=50, endpoint=True).tolist()
|
||||
# plt.figure(figsize=(10, 6))
|
||||
# plt.plot(x, recall, color='red', label='recall')
|
||||
# plt.plot(x, recall_TN, color='black', label='recall_TN')
|
||||
# plt.plot(x, PrecisePos, color='blue', label='PrecisePos')
|
||||
# plt.plot(x, PreciseNeg, color='green', label='PreciseNeg')
|
||||
# plt.legend()
|
||||
# plt.xlabel('threshold')
|
||||
# # plt.ylabel('Similarity')
|
||||
# plt.grid(True, linestyle='--', alpha=0.5)
|
||||
# plt.savefig('accuracy_recall_grid.png')
|
||||
# plt.show()
|
||||
# plt.close()
|
||||
#
|
||||
#
|
||||
# def compute_accuracy_recall(score, labels):
|
||||
# th = 0.1
|
||||
# squence = np.linspace(-1, 1, num=50)
|
||||
# # squence = [0.4]
|
||||
# recall, PrecisePos, PreciseNeg, recall_TN = [], [], [], []
|
||||
# for th in squence:
|
||||
# t_score = (score > th)
|
||||
# t_labels = (labels == 1)
|
||||
# # print(t_score)
|
||||
# # print(t_labels)
|
||||
# TP = np.sum(np.logical_and(t_score, t_labels))
|
||||
# FN = np.sum(np.logical_and(np.logical_not(t_score), t_labels))
|
||||
# f_score = (score < th)
|
||||
# f_labels = (labels == 0)
|
||||
# TN = np.sum(np.logical_and(f_score, f_labels))
|
||||
# FP = np.sum(np.logical_and(np.logical_not(f_score), f_labels))
|
||||
# print("Threshold:{} TP:{},FP:{},TN:{},FN:{}".format(th, TP, FP, TN, FN))
|
||||
#
|
||||
# PrecisePos.append(0 if TP / (TP + FP) == 'nan' else TP / (TP + FP))
|
||||
# PreciseNeg.append(0 if TN == 0 else TN / (TN + FN))
|
||||
# recall.append(0 if TP == 0 else TP / (TP + FN))
|
||||
# recall_TN.append(0 if TN == 0 else TN / (TN + FP))
|
||||
# showgrid(recall, recall_TN, PrecisePos, PreciseNeg)
|
||||
#
|
||||
#
|
||||
# def compute_accuracy(feature_dict, pair_list, test_root):
|
||||
# with open(pair_list, 'r') as f:
|
||||
# pairs = f.readlines()
|
||||
#
|
||||
# similarities = []
|
||||
# labels = []
|
||||
# for pair in pairs:
|
||||
# img1, img2, label = pair.split()
|
||||
# img1 = osp.join(test_root, img1)
|
||||
# img2 = osp.join(test_root, img2)
|
||||
# feature1 = feature_dict[img1].cpu().numpy()
|
||||
# feature2 = feature_dict[img2].cpu().numpy()
|
||||
# label = int(label)
|
||||
#
|
||||
# similarity = cosin_metric(feature1, feature2)
|
||||
# similarities.append(similarity)
|
||||
# labels.append(label)
|
||||
#
|
||||
# accuracy, threshold = threshold_search(similarities, labels)
|
||||
# # print('similarities >> {}'.format(similarities))
|
||||
# # print('labels >> {}'.format(labels))
|
||||
# compute_accuracy_recall(np.array(similarities), np.array(labels))
|
||||
# return accuracy, threshold
|
||||
|
||||
|
||||
# def deal_group_pair(pairList1, pairList2):
|
||||
# allsimilarity = []
|
||||
# one_similarity = []
|
||||
# for pair1 in pairList1:
|
||||
# for pair2 in pairList2:
|
||||
# similarity = cosin_metric(pair1.cpu().numpy(), pair2.cpu().numpy())
|
||||
# one_similarity.append(similarity)
|
||||
# allsimilarity.append(max(one_similarity)) # 最大值
|
||||
# # allsimilarity.append(sum(one_similarity)/len(one_similarity)) # 均值
|
||||
# # allsimilarity.append(statistics.median(one_similarity)) # 中位数
|
||||
# # print(allsimilarity)
|
||||
# # print(labels)
|
||||
# return allsimilarity
|
||||
|
||||
|
||||
# def compute_group_accuracy(content_list_read):
|
||||
# allSimilarity, allLabel = [], []
|
||||
# for data_loaded in content_list_read:
|
||||
# one_group_list = []
|
||||
# for i in range(2):
|
||||
# images = [osp.join(conf.test_val, img) for img in data_loaded[i]]
|
||||
# group = group_image(images, conf.test_batch_size)
|
||||
# d = featurize(group[0], conf.test_transform, model, conf.device)
|
||||
# one_group_list.append(d.values())
|
||||
# similarity = deal_group_pair(one_group_list[0], one_group_list[1])
|
||||
# allLabel.append(data_loaded[-1])
|
||||
# allSimilarity.extend(similarity)
|
||||
# # print(allSimilarity)
|
||||
# # print(allLabel)
|
||||
# return allSimilarity, allLabel
|
||||
|
||||
|
||||
# def compute_contrast_accuracy(content_list_read):
|
||||
# npairs = 50
|
||||
#
|
||||
# same_folder_pairs = content_list_read['same_folder_pairs']
|
||||
# cross_folder_pairs = content_list_read['cross_folder_pairs']
|
||||
#
|
||||
# npairs = min((len(same_folder_pairs), len(cross_folder_pairs)))
|
||||
#
|
||||
# Encoder = FeatsInterface(conf)
|
||||
#
|
||||
# same_pairs = same_folder_pairs[:npairs]
|
||||
# cross_pairs = cross_folder_pairs[:npairs]
|
||||
#
|
||||
# same_pairs_similarity = []
|
||||
# for i in range(len(same_pairs)):
|
||||
# images_a = [osp.join(conf.test_val, img) for img in same_pairs[i][0]]
|
||||
# images_b = [osp.join(conf.test_val, img) for img in same_pairs[i][1]]
|
||||
#
|
||||
# feats_a = Encoder.inference(images_a)
|
||||
# feats_b = Encoder.inference(images_b)
|
||||
# # matrix = 1- np.maximum(0.0, cdist(feats_a, feats_b, 'cosine'))
|
||||
# matrix = 1 - cdist(feats_a, feats_b, 'cosine')
|
||||
#
|
||||
# feats_am = np.mean(feats_a, axis=0, keepdims=True)
|
||||
# feats_bm = np.mean(feats_b, axis=0, keepdims=True)
|
||||
# matrixm = 1 - np.maximum(0.0, cdist(feats_am, feats_bm, 'cosine'))
|
||||
#
|
||||
# same_pairs_similarity.append(np.mean(matrix))
|
||||
#
|
||||
# '''保存相同 Barcode 图像对'''
|
||||
# # foldi = os.path.join('./result/same', f'{i}')
|
||||
# # if os.path.exists(foldi):
|
||||
# # shutil.rmtree(foldi)
|
||||
# # os.makedirs(foldi)
|
||||
# # else:
|
||||
# # os.makedirs(foldi)
|
||||
# # for ipt in range(len(images_a)):
|
||||
# # source_path = images_a[ipt]
|
||||
# # destination_path = os.path.join(foldi, f'a_{ipt}.png')
|
||||
# # shutil.copy2(source_path, destination_path)
|
||||
# # for ipt in range(len(images_b)):
|
||||
# # source_path = images_b[ipt]
|
||||
# # destination_path = os.path.join(foldi, f'b_{ipt}.png')
|
||||
# # shutil.copy2(source_path, destination_path)
|
||||
#
|
||||
# cross_pairs_similarity = []
|
||||
# for i in range(len(cross_pairs)):
|
||||
# images_a = [osp.join(conf.test_val, img) for img in cross_pairs[i][0]]
|
||||
# images_b = [osp.join(conf.test_val, img) for img in cross_pairs[i][1]]
|
||||
#
|
||||
# feats_a = Encoder.inference(images_a)
|
||||
# feats_b = Encoder.inference(images_b)
|
||||
# # matrix = 1- np.maximum(0.0, cdist(feats_a, feats_b, 'cosine'))
|
||||
# matrix = 1 - cdist(feats_a, feats_b, 'cosine')
|
||||
#
|
||||
# feats_am = np.mean(feats_a, axis=0, keepdims=True)
|
||||
# feats_bm = np.mean(feats_b, axis=0, keepdims=True)
|
||||
# matrixm = 1 - np.maximum(0.0, cdist(feats_am, feats_bm, 'cosine'))
|
||||
#
|
||||
# cross_pairs_similarity.append(np.mean(matrix))
|
||||
#
|
||||
# '''保存不同 Barcode 图像对'''
|
||||
# # foldi = os.path.join('./result/cross', f'{i}')
|
||||
# # if os.path.exists(foldi):
|
||||
# # shutil.rmtree(foldi)
|
||||
# # os.makedirs(foldi)
|
||||
# # else:
|
||||
# # os.makedirs(foldi)
|
||||
# # for ipt in range(len(images_a)):
|
||||
# # source_path = images_a[ipt]
|
||||
# # destination_path = os.path.join(foldi, f'a_{ipt}.png')
|
||||
# # shutil.copy2(source_path, destination_path)
|
||||
# # for ipt in range(len(images_b)):
|
||||
# # source_path = images_b[ipt]
|
||||
# # destination_path = os.path.join(foldi, f'b_{ipt}.png')
|
||||
# # shutil.copy2(source_path, destination_path)
|
||||
#
|
||||
# Thresh = np.linspace(-0.2, 1, 100)
|
||||
#
|
||||
# Same = np.array(same_pairs_similarity)
|
||||
# Cross = np.array(cross_pairs_similarity)
|
||||
#
|
||||
# fig, axs = plt.subplots(2, 1)
|
||||
# axs[0].hist(Same, bins=60, edgecolor='black')
|
||||
# axs[0].set_xlim([-0.2, 1])
|
||||
# axs[0].set_title('Same Barcode')
|
||||
#
|
||||
# axs[1].hist(Cross, bins=60, edgecolor='black')
|
||||
# axs[1].set_xlim([-0.2, 1])
|
||||
# axs[1].set_title('Cross Barcode')
|
||||
#
|
||||
# TPFN = len(Same)
|
||||
# TNFP = len(Cross)
|
||||
# Recall_Pos, Recall_Neg = [], []
|
||||
# Precision_Pos, Precision_Neg = [], []
|
||||
# Correct = []
|
||||
# for th in Thresh:
|
||||
# TP = np.sum(Same > th)
|
||||
# FN = TPFN - TP
|
||||
# TN = np.sum(Cross < th)
|
||||
# FP = TNFP - TN
|
||||
#
|
||||
# Recall_Pos.append(TP / TPFN)
|
||||
# Recall_Neg.append(TN / TNFP)
|
||||
# Precision_Pos.append(TP / (TP + FP))
|
||||
# Precision_Neg.append(TN / (TN + FN))
|
||||
# Correct.append((TN + TP) / (TPFN + TNFP))
|
||||
#
|
||||
# fig, ax = plt.subplots()
|
||||
# ax.plot(Thresh, Correct, 'r', label='Correct: (TN+TP)/(TPFN+TNFP)')
|
||||
# ax.plot(Thresh, Recall_Pos, 'b', label='Recall_Pos: TP/TPFN')
|
||||
# ax.plot(Thresh, Recall_Neg, 'g', label='Recall_Neg: TN/TNFP')
|
||||
# ax.plot(Thresh, Precision_Pos, 'c', label='Precision_Pos: TP/(TP+FP)')
|
||||
# ax.plot(Thresh, Precision_Neg, 'm', label='Precision_Neg: TN/(TN+FN)')
|
||||
#
|
||||
# ax.set_xlim([0, 1])
|
||||
# ax.set_ylim([0, 1])
|
||||
# ax.grid(True)
|
||||
# ax.set_title('PrecisePos & PreciseNeg')
|
||||
# ax.legend()
|
||||
# plt.show()
|
||||
#
|
||||
# print("Haved done!!!")
|
||||
#
|
||||
#
|
||||
# if __name__ == '__main__':
|
||||
#
|
||||
# # Network Setup
|
||||
# if conf.testbackbone == 'resnet18':
|
||||
# # model = ResIRSE(conf.img_size, conf.embedding_size, conf.drop_ratio).to(conf.device)
|
||||
# model = resnet18().to(conf.device)
|
||||
# # elif conf.testbackbone == 'resnet34':
|
||||
# # model = resnet34().to(conf.device)
|
||||
# # elif conf.testbackbone == 'resnet50':
|
||||
# # model = resnet50().to(conf.device)
|
||||
# # elif conf.testbackbone == 'mobilevit_s':
|
||||
# # model = mobilevit_s().to(conf.device)
|
||||
# # elif conf.testbackbone == 'mobilenetv3':
|
||||
# # model = MobileNetV3_Small().to(conf.device)
|
||||
# # elif conf.testbackbone == 'mobilenet_v1':
|
||||
# # model = mobilenet_v1().to(conf.device)
|
||||
# # elif conf.testbackbone == 'PPLCNET_x1_0':
|
||||
# # model = PPLCNET_x1_0().to(conf.device)
|
||||
# # elif conf.testbackbone == 'PPLCNET_x0_5':
|
||||
# # model = PPLCNET_x0_5().to(conf.device)
|
||||
# # elif conf.backbone == 'PPLCNET_x2_5':
|
||||
# # model = PPLCNET_x2_5().to(conf.device)
|
||||
# # elif conf.testbackbone == 'mobilenet_v2':
|
||||
# # model = mobilenet_v2().to(conf.device)
|
||||
# # elif conf.testbackbone == 'resnet14':
|
||||
# # model = resnet14().to(conf.device)
|
||||
# else:
|
||||
# raise ValueError('Have not model {}'.format(conf.backbone))
|
||||
#
|
||||
# print('load model {} '.format(conf.testbackbone))
|
||||
# # model = nn.DataParallel(model).to(conf.device)
|
||||
# model.load_state_dict(torch.load(conf.test_model, map_location=conf.device))
|
||||
# model.eval()
|
||||
# if not conf.group_test:
|
||||
# images = unique_image(conf.test_list)
|
||||
# images = [osp.join(conf.test_val, img) for img in images]
|
||||
#
|
||||
# groups = group_image(images, conf.test_batch_size) ##根据batch_size取图片
|
||||
#
|
||||
# feature_dict = dict()
|
||||
# for group in groups:
|
||||
# d = featurize(group, conf.test_transform, model, conf.device)
|
||||
# feature_dict.update(d)
|
||||
# # print('feature_dict', feature_dict)
|
||||
# accuracy, threshold = compute_accuracy(feature_dict, conf.test_list, conf.test_val)
|
||||
#
|
||||
# print(
|
||||
# f"Test Model: {conf.test_model}\n"
|
||||
# f"Accuracy: {accuracy:.3f}\n"
|
||||
# f"Threshold: {threshold:.3f}\n"
|
||||
# )
|
||||
# elif conf.group_test:
|
||||
# """
|
||||
# conf.test_val: 测试数据集地址
|
||||
# conf.test_group_json:测试数据分组配置文件
|
||||
# """
|
||||
# filename = conf.test_group_json
|
||||
#
|
||||
# filename = "../cl/images_1.json"
|
||||
# with open(filename, 'r', encoding='utf-8') as file:
|
||||
# content_list_read = json.load(file)
|
||||
#
|
||||
# compute_contrast_accuracy(content_list_read)
|
||||
|
||||
# =============================================================================
|
||||
# Similarity, Label = compute_group_accuracy(content_list_read)
|
||||
# print('allSimilarity >> {}'.format(Similarity))
|
||||
# print('allLabel >> {}'.format(Label))
|
||||
# compute_accuracy_recall(np.array(Similarity), np.array(Label))
|
||||
# # compute_group_accuracy(data_loaded)
|
||||
#
|
||||
# =============================================================================
|
12
detecttracking/contrast/feat_extract/resnet_vit/.idea/contrastInference.iml
generated
Normal file
12
detecttracking/contrast/feat_extract/resnet_vit/.idea/contrastInference.iml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.8 (my_env)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PyDocumentationSettings">
|
||||
<option name="format" value="PLAIN" />
|
||||
<option name="myDocStringFormat" value="Plain" />
|
||||
</component>
|
||||
</module>
|
14
detecttracking/contrast/feat_extract/resnet_vit/.idea/deployment.xml
generated
Normal file
14
detecttracking/contrast/feat_extract/resnet_vit/.idea/deployment.xml
generated
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PublishConfigData" remoteFilesAllowedToDisappearOnAutoupload="false">
|
||||
<serverData>
|
||||
<paths name="lc@192.168.1.142:22 password">
|
||||
<serverdata>
|
||||
<mappings>
|
||||
<mapping local="$PROJECT_DIR$" web="/" />
|
||||
</mappings>
|
||||
</serverdata>
|
||||
</paths>
|
||||
</serverData>
|
||||
</component>
|
||||
</project>
|
12
detecttracking/contrast/feat_extract/resnet_vit/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
12
detecttracking/contrast/feat_extract/resnet_vit/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="ignoredErrors">
|
||||
<list>
|
||||
<option value="N803" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
6
detecttracking/contrast/feat_extract/resnet_vit/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
detecttracking/contrast/feat_extract/resnet_vit/.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
7
detecttracking/contrast/feat_extract/resnet_vit/.idea/misc.xml
generated
Normal file
7
detecttracking/contrast/feat_extract/resnet_vit/.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.8 (my_env)" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (my_env)" project-jdk-type="Python SDK" />
|
||||
</project>
|
8
detecttracking/contrast/feat_extract/resnet_vit/.idea/modules.xml
generated
Normal file
8
detecttracking/contrast/feat_extract/resnet_vit/.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/contrastInference.iml" filepath="$PROJECT_DIR$/.idea/contrastInference.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1 @@
|
||||
# from .config import config
|
84
detecttracking/contrast/feat_extract/resnet_vit/config.py
Normal file
84
detecttracking/contrast/feat_extract/resnet_vit/config.py
Normal file
@ -0,0 +1,84 @@
|
||||
import torch
|
||||
import torchvision.transforms as T
|
||||
|
||||
|
||||
class Config:
|
||||
# network settings
|
||||
backbone = 'vit' # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3_small, mobilenetv3_large, mobilenet_v1, PPLCNET_x1_0, PPLCNET_x0_5, PPLCNET_x2_5]
|
||||
metric = 'softmax' # [cosface, arcface, softmax]
|
||||
cbam = True
|
||||
embedding_size = 256 # 256
|
||||
drop_ratio = 0.5
|
||||
img_size = 224
|
||||
|
||||
teacher = 'vit' # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3_small, mobilenetv3_large, mobilenet_v1, PPLCNET_x1_0, PPLCNET_x0_5, PPLCNET_x2_5]
|
||||
student = 'resnet'
|
||||
# data preprocess
|
||||
# input_shape = [1, 128, 128]
|
||||
"""transforms.RandomCrop(size),
|
||||
transforms.RandomVerticalFlip(p=0.5),
|
||||
transforms.RandomHorizontalFlip(),
|
||||
RandomRotate(15, 0.3),
|
||||
# RandomGaussianBlur()"""
|
||||
|
||||
train_transform = T.Compose([
|
||||
T.ToTensor(),
|
||||
T.Resize((img_size, img_size)),
|
||||
# T.RandomCrop(img_size*4//5),
|
||||
# T.RandomHorizontalFlip(p=0.5),
|
||||
T.RandomRotation(180),
|
||||
T.ColorJitter(brightness=0.5),
|
||||
T.ConvertImageDtype(torch.float32),
|
||||
T.Normalize(mean=[0.5], std=[0.5]),
|
||||
])
|
||||
test_transform = T.Compose([
|
||||
T.ToTensor(),
|
||||
T.Resize((img_size, img_size)),
|
||||
T.ConvertImageDtype(torch.float32),
|
||||
T.Normalize(mean=[0.5], std=[0.5]),
|
||||
])
|
||||
|
||||
# dataset
|
||||
train_root = './data/2250_train/train' # 初始筛选过一次的数据集
|
||||
# train_root = './data/0625_train/train'
|
||||
test_root = "./data/2250_train/val/"
|
||||
# test_root = "./data/0625_train/val"
|
||||
|
||||
test_list = "./data/2250_train/val_pair.txt"
|
||||
test_group_json = "./data/2250_train/cross_same.json"
|
||||
# test_group_json = "./data/0625_train/cross_same.json"
|
||||
# test_list = "./data/test_data_100/val_pair.txt"
|
||||
|
||||
# training settings
|
||||
checkpoints = "checkpoints/vit_b_16_0815/" # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3]
|
||||
restore = True
|
||||
# restore_model = "checkpoints/renet18_2250_0315/best_resnet18_2250_0315.pth" # best_resnet18_1491_0306.pth
|
||||
restore_model = "checkpoints/vit_b_16_0730/best.pth" # best_resnet18_1491_0306.pth
|
||||
|
||||
# test_model = "./checkpoints/renet18_1887_0311/best_resnet18_1887_0311.pth"
|
||||
testbackbone = 'resnet18' # [resnet18, mobilevit_s, mobilenet_v2, mobilenetv3_small, mobilenetv3_large, mobilenet_v1, PPLCNET_x1_0, PPLCNET_x0_5]
|
||||
# test_val = "./data/2250_train"
|
||||
test_val = "./data/0625_train"
|
||||
test_model = "checkpoints/resnet18_0721/best.pth"
|
||||
|
||||
train_batch_size = 128 # 256
|
||||
test_batch_size = 256 # 256
|
||||
|
||||
|
||||
epoch = 300
|
||||
optimizer = 'adamw' # ['sgd', 'adam', 'adamw']
|
||||
lr = 1e-3 # 1e-2
|
||||
lr_step = 10 # 10
|
||||
lr_decay = 0.95 # 0.98
|
||||
weight_decay = 5e-4
|
||||
loss = 'focal_loss' # ['focal_loss', 'cross_entropy']
|
||||
device = torch.device('cuda:1' if torch.cuda.is_available() else 'cpu')
|
||||
# device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
|
||||
|
||||
pin_memory = True # if memory is large, set it True to speed up a bit
|
||||
num_workers = 4 # dataloader
|
||||
|
||||
group_test = True
|
||||
# group_test = False
|
||||
|
||||
config = Config()
|
103
detecttracking/contrast/feat_extract/resnet_vit/inference.py
Normal file
103
detecttracking/contrast/feat_extract/resnet_vit/inference.py
Normal file
@ -0,0 +1,103 @@
|
||||
import os
|
||||
import os.path as osp
|
||||
|
||||
import torch
|
||||
|
||||
import numpy as np
|
||||
from model import resnet18
|
||||
from PIL import Image
|
||||
|
||||
from torch.nn.functional import softmax
|
||||
from config import config as conf
|
||||
import time
|
||||
|
||||
embedding_size = conf.embedding_size
|
||||
img_size = conf.img_size
|
||||
device = conf.device
|
||||
|
||||
def load_contrast_model():
|
||||
model = resnet18().to(conf.device)
|
||||
model.load_state_dict(torch.load(conf.test_model, map_location=conf.device))
|
||||
model.eval()
|
||||
print('load model {} '.format(conf.testbackbone))
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def group_image(imageDirs, batch) -> list:
|
||||
images = []
|
||||
"""Group image paths by batch size"""
|
||||
with os.scandir(imageDirs) as entries:
|
||||
for imgpth in entries:
|
||||
print(imgpth)
|
||||
images.append(os.sep.join([imageDirs, imgpth.name]))
|
||||
print(f"{len(images)} images in {imageDirs}")
|
||||
size = len(images)
|
||||
res = []
|
||||
for i in range(0, size, batch):
|
||||
end = min(batch + i, size)
|
||||
res.append(images[i: end])
|
||||
return res
|
||||
|
||||
def test_preprocess(images: list, transform) -> torch.Tensor:
|
||||
res = []
|
||||
for img in images:
|
||||
# print(img)
|
||||
im = Image.open(img)
|
||||
im = transform(im)
|
||||
res.append(im)
|
||||
# data = torch.cat(res, dim=0) # shape: (batch, 128, 128)
|
||||
# data = data[:, None, :, :] # shape: (batch, 1, 128, 128)
|
||||
data = torch.stack(res)
|
||||
return data
|
||||
|
||||
def featurize(images: list, transform, net, device) -> dict:
|
||||
"""featurize each image and save into a dictionary
|
||||
Args:
|
||||
images: image paths
|
||||
transform: test transform
|
||||
net: pretrained model
|
||||
device: cpu or cuda
|
||||
Returns:
|
||||
Dict (key: imagePath, value: feature)
|
||||
"""
|
||||
data = test_preprocess(images, transform)
|
||||
data = data.to(device)
|
||||
net = net.to(device)
|
||||
with torch.no_grad():
|
||||
features = net(data)
|
||||
# res = {img: feature for (img, feature) in zip(images, features)}
|
||||
return features
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Network Setup
|
||||
if conf.testbackbone == 'resnet18':
|
||||
model = resnet18().to(device)
|
||||
else:
|
||||
raise ValueError('Have not model {}'.format(conf.backbone))
|
||||
|
||||
print('load model {} '.format(conf.testbackbone))
|
||||
# model = nn.DataParallel(model).to(conf.device)
|
||||
model.load_state_dict(torch.load(conf.test_model, map_location=conf.device))
|
||||
model.eval()
|
||||
|
||||
# images = unique_image(conf.test_list)
|
||||
# images = [osp.join(conf.test_val, img) for img in images]
|
||||
# print('images', images)
|
||||
# images = ['./data/2250_train/val/6920616313186/6920616313186_6920616313186_20240220-124502_53d2e103-ae3a-4689-b745-9d8723b770fe_front_returnGood_70f75407b7ae_31_01.jpg']
|
||||
|
||||
|
||||
# groups = group_image(conf.test_val, conf.test_batch_size) ##根据batch_size取图片
|
||||
groups = group_image('img_test', 1) ##根据batch_size取图片, 默认batch_size = 8
|
||||
|
||||
feature_dict = dict()
|
||||
for group in groups:
|
||||
s = time.time()
|
||||
features = featurize(group, conf.test_transform, model, conf.device)
|
||||
e = time.time()
|
||||
print('time: {}'.format(e - s))
|
||||
# out = softmax(features, dim=1).argmax(dim=1)
|
||||
# print('d >>> {}'. format(out))
|
||||
# feature_dict.update(d)
|
@ -0,0 +1 @@
|
||||
from .resnet_pre import resnet18, resnet34, resnet50, resnet14
|
@ -0,0 +1,462 @@
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
from config import config as conf
|
||||
|
||||
try:
|
||||
from torch.hub import load_state_dict_from_url
|
||||
except ImportError:
|
||||
from torch.utils.model_zoo import load_url as load_state_dict_from_url
|
||||
# from .utils import load_state_dict_from_url
|
||||
|
||||
__all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101',
|
||||
'resnet152', 'resnext50_32x4d', 'resnext101_32x8d',
|
||||
'wide_resnet50_2', 'wide_resnet101_2']
|
||||
|
||||
model_urls = {
|
||||
'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth',
|
||||
'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth',
|
||||
'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
|
||||
'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth',
|
||||
'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth',
|
||||
'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth',
|
||||
'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth',
|
||||
'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth',
|
||||
'wide_resnet101_2': 'https://download.pytorch.org/models/wide_resnet101_2-32ee1156.pth',
|
||||
}
|
||||
|
||||
|
||||
def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
|
||||
"""3x3 convolution with padding"""
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
|
||||
padding=dilation, groups=groups, bias=False, dilation=dilation)
|
||||
|
||||
def conv1x1(in_planes, out_planes, stride=1):
|
||||
"""1x1 convolution"""
|
||||
return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
|
||||
|
||||
|
||||
class SpatialAttention(nn.Module):
|
||||
def __init__(self, kernel_size=7):
|
||||
super(SpatialAttention, self).__init__()
|
||||
|
||||
assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
|
||||
padding = 3 if kernel_size == 7 else 1
|
||||
|
||||
self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
|
||||
self.sigmoid = nn.Sigmoid()
|
||||
|
||||
def forward(self, x):
|
||||
avg_out = torch.mean(x, dim=1, keepdim=True)
|
||||
max_out, _ = torch.max(x, dim=1, keepdim=True)
|
||||
x = torch.cat([avg_out, max_out], dim=1)
|
||||
x = self.conv1(x)
|
||||
return self.sigmoid(x)
|
||||
|
||||
class BasicBlock(nn.Module):
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
|
||||
base_width=64, dilation=1, norm_layer=None, cam=False, bam=False):
|
||||
super(BasicBlock, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
if groups != 1 or base_width != 64:
|
||||
raise ValueError('BasicBlock only supports groups=1 and base_width=64')
|
||||
if dilation > 1:
|
||||
raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
|
||||
self.cam = cam
|
||||
self.bam = bam
|
||||
# Both self.conv1 and self.downsample layers downsample the input when stride != 1
|
||||
self.conv1 = conv3x3(inplanes, planes, stride)
|
||||
self.bn1 = norm_layer(planes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.conv2 = conv3x3(planes, planes)
|
||||
self.bn2 = norm_layer(planes)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
if self.cam:
|
||||
if planes == 64:
|
||||
self.globalAvgPool = nn.AvgPool2d(56, stride=1)
|
||||
elif planes == 128:
|
||||
self.globalAvgPool = nn.AvgPool2d(28, stride=1)
|
||||
elif planes == 256:
|
||||
self.globalAvgPool = nn.AvgPool2d(14, stride=1)
|
||||
elif planes == 512:
|
||||
self.globalAvgPool = nn.AvgPool2d(7, stride=1)
|
||||
|
||||
self.fc1 = nn.Linear(in_features=planes, out_features=round(planes / 16))
|
||||
self.fc2 = nn.Linear(in_features=round(planes / 16), out_features=planes)
|
||||
self.sigmod = nn.Sigmoid()
|
||||
if self.bam:
|
||||
self.bam = SpatialAttention()
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
if self.cam:
|
||||
ori_out = self.globalAvgPool(out)
|
||||
out = out.view(out.size(0), -1)
|
||||
out = self.fc1(out)
|
||||
out = self.relu(out)
|
||||
out = self.fc2(out)
|
||||
out = self.sigmod(out)
|
||||
out = out.view(out.size(0), out.size(-1), 1, 1)
|
||||
out = out * ori_out
|
||||
|
||||
if self.bam:
|
||||
out = out*self.bam(out)
|
||||
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class Bottleneck(nn.Module):
|
||||
# Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2)
|
||||
# while original implementation places the stride at the first 1x1 convolution(self.conv1)
|
||||
# according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385.
|
||||
# This variant is also known as ResNet V1.5 and improves accuracy according to
|
||||
# https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch.
|
||||
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
|
||||
base_width=64, dilation=1, norm_layer=None, cam=False, bam=False):
|
||||
super(Bottleneck, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
width = int(planes * (base_width / 64.)) * groups
|
||||
self.cam = cam
|
||||
self.bam = bam
|
||||
# Both self.conv2 and self.downsample layers downsample the input when stride != 1
|
||||
self.conv1 = conv1x1(inplanes, width)
|
||||
self.bn1 = norm_layer(width)
|
||||
self.conv2 = conv3x3(width, width, stride, groups, dilation)
|
||||
self.bn2 = norm_layer(width)
|
||||
self.conv3 = conv1x1(width, planes * self.expansion)
|
||||
self.bn3 = norm_layer(planes * self.expansion)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
if self.cam:
|
||||
if planes == 64:
|
||||
self.globalAvgPool = nn.AvgPool2d(56, stride=1)
|
||||
elif planes == 128:
|
||||
self.globalAvgPool = nn.AvgPool2d(28, stride=1)
|
||||
elif planes == 256:
|
||||
self.globalAvgPool = nn.AvgPool2d(14, stride=1)
|
||||
elif planes == 512:
|
||||
self.globalAvgPool = nn.AvgPool2d(7, stride=1)
|
||||
|
||||
self.fc1 = nn.Linear(planes * self.expansion, round(planes / 4))
|
||||
self.fc2 = nn.Linear(round(planes / 4), planes * self.expansion)
|
||||
self.sigmod = nn.Sigmoid()
|
||||
|
||||
def forward(self, x):
|
||||
identity = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv2(out)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
identity = self.downsample(x)
|
||||
|
||||
if self.cam:
|
||||
ori_out = self.globalAvgPool(out)
|
||||
out = out.view(out.size(0), -1)
|
||||
out = self.fc1(out)
|
||||
out = self.relu(out)
|
||||
out = self.fc2(out)
|
||||
out = self.sigmod(out)
|
||||
out = out.view(out.size(0), out.size(-1), 1, 1)
|
||||
out = out * ori_out
|
||||
out += identity
|
||||
out = self.relu(out)
|
||||
return out
|
||||
|
||||
|
||||
class ResNet(nn.Module):
|
||||
|
||||
def __init__(self, block, layers, num_classes=conf.embedding_size, zero_init_residual=False,
|
||||
groups=1, width_per_group=64, replace_stride_with_dilation=None,
|
||||
norm_layer=None, scale=0.75):
|
||||
super(ResNet, self).__init__()
|
||||
if norm_layer is None:
|
||||
norm_layer = nn.BatchNorm2d
|
||||
self._norm_layer = norm_layer
|
||||
|
||||
self.inplanes = 64
|
||||
self.dilation = 1
|
||||
if replace_stride_with_dilation is None:
|
||||
# each element in the tuple indicates if we should replace
|
||||
# the 2x2 stride with a dilated convolution instead
|
||||
replace_stride_with_dilation = [False, False, False]
|
||||
if len(replace_stride_with_dilation) != 3:
|
||||
raise ValueError("replace_stride_with_dilation should be None "
|
||||
"or a 3-element tuple, got {}".format(replace_stride_with_dilation))
|
||||
self.groups = groups
|
||||
self.base_width = width_per_group
|
||||
self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
|
||||
bias=False)
|
||||
self.bn1 = norm_layer(self.inplanes)
|
||||
self.relu = nn.ReLU(inplace=True)
|
||||
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
||||
self.layer1 = self._make_layer(block, int(64*scale), layers[0])
|
||||
self.layer2 = self._make_layer(block, int(128*scale), layers[1], stride=2,
|
||||
dilate=replace_stride_with_dilation[0])
|
||||
self.layer3 = self._make_layer(block, int(256*scale), layers[2], stride=2,
|
||||
dilate=replace_stride_with_dilation[1])
|
||||
self.layer4 = self._make_layer(block, int(512*scale), layers[3], stride=2,
|
||||
dilate=replace_stride_with_dilation[2])
|
||||
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
|
||||
self.fc = nn.Linear(int(512 * block.expansion*scale), num_classes)
|
||||
|
||||
for m in self.modules():
|
||||
if isinstance(m, nn.Conv2d):
|
||||
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
|
||||
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
|
||||
nn.init.constant_(m.weight, 1)
|
||||
nn.init.constant_(m.bias, 0)
|
||||
|
||||
# Zero-initialize the last BN in each residual branch,
|
||||
# so that the residual branch starts with zeros, and each residual block behaves like an identity.
|
||||
# This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
|
||||
if zero_init_residual:
|
||||
for m in self.modules():
|
||||
if isinstance(m, Bottleneck):
|
||||
nn.init.constant_(m.bn3.weight, 0)
|
||||
elif isinstance(m, BasicBlock):
|
||||
nn.init.constant_(m.bn2.weight, 0)
|
||||
|
||||
def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
|
||||
norm_layer = self._norm_layer
|
||||
downsample = None
|
||||
previous_dilation = self.dilation
|
||||
if dilate:
|
||||
self.dilation *= stride
|
||||
stride = 1
|
||||
if stride != 1 or self.inplanes != planes * block.expansion:
|
||||
downsample = nn.Sequential(
|
||||
conv1x1(self.inplanes, planes * block.expansion, stride),
|
||||
norm_layer(planes * block.expansion),
|
||||
)
|
||||
|
||||
layers = []
|
||||
layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
|
||||
self.base_width, previous_dilation, norm_layer))
|
||||
self.inplanes = planes * block.expansion
|
||||
for _ in range(1, blocks):
|
||||
layers.append(block(self.inplanes, planes, groups=self.groups,
|
||||
base_width=self.base_width, dilation=self.dilation,
|
||||
norm_layer=norm_layer))
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def _forward_impl(self, x):
|
||||
# See note [TorchScript super()]
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.maxpool(x)
|
||||
|
||||
x = self.layer1(x)
|
||||
x = self.layer2(x)
|
||||
x = self.layer3(x)
|
||||
x = self.layer4(x)
|
||||
|
||||
# print('poolBefore', x.shape)
|
||||
x = self.avgpool(x)
|
||||
# print('poolAfter', x.shape)
|
||||
x = torch.flatten(x, 1)
|
||||
# print('fcBefore',x.shape)
|
||||
x = self.fc(x)
|
||||
|
||||
# print('fcAfter',x.shape)
|
||||
|
||||
return x
|
||||
|
||||
def forward(self, x):
|
||||
return self._forward_impl(x)
|
||||
|
||||
|
||||
# def _resnet(arch, block, layers, pretrained, progress, **kwargs):
|
||||
# model = ResNet(block, layers, **kwargs)
|
||||
# if pretrained:
|
||||
# state_dict = load_state_dict_from_url(model_urls[arch],
|
||||
# progress=progress)
|
||||
# model.load_state_dict(state_dict, strict=False)
|
||||
# return model
|
||||
def _resnet(arch, block, layers, pretrained, progress, **kwargs):
|
||||
model = ResNet(block, layers, **kwargs)
|
||||
if pretrained:
|
||||
state_dict = load_state_dict_from_url(model_urls[arch],
|
||||
progress=progress)
|
||||
|
||||
src_state_dict = state_dict
|
||||
target_state_dict = model.state_dict()
|
||||
skip_keys = []
|
||||
# skip mismatch size tensors in case of pretraining
|
||||
for k in src_state_dict.keys():
|
||||
if k not in target_state_dict:
|
||||
continue
|
||||
if src_state_dict[k].size() != target_state_dict[k].size():
|
||||
skip_keys.append(k)
|
||||
for k in skip_keys:
|
||||
del src_state_dict[k]
|
||||
missing_keys, unexpected_keys = model.load_state_dict(src_state_dict, strict=False)
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def resnet14(pretrained=True, progress=True, **kwargs):
|
||||
r"""ResNet-14 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet18', BasicBlock, [2, 1, 1, 2], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet18(pretrained=True, progress=True, **kwargs):
|
||||
r"""ResNet-18 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet18', BasicBlock, [2, 2, 2, 2], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet34(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-34 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet34', BasicBlock, [3, 4, 6, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet50(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-50 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet50', Bottleneck, [3, 4, 6, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet101(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-101 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet101', Bottleneck, [3, 4, 23, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnet152(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNet-152 model from
|
||||
`"Deep Residual Learning for Image Recognition" <https://arxiv.org/pdf/1512.03385.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
return _resnet('resnet152', Bottleneck, [3, 8, 36, 3], pretrained, progress,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def resnext50_32x4d(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNeXt-50 32x4d model from
|
||||
`"Aggregated Residual Transformation for Deep Neural Networks" <https://arxiv.org/pdf/1611.05431.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['groups'] = 32
|
||||
kwargs['width_per_group'] = 4
|
||||
return _resnet('resnext50_32x4d', Bottleneck, [3, 4, 6, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def resnext101_32x8d(pretrained=False, progress=True, **kwargs):
|
||||
r"""ResNeXt-101 32x8d model from
|
||||
`"Aggregated Residual Transformation for Deep Neural Networks" <https://arxiv.org/pdf/1611.05431.pdf>`_
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['groups'] = 32
|
||||
kwargs['width_per_group'] = 8
|
||||
return _resnet('resnext101_32x8d', Bottleneck, [3, 4, 23, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def wide_resnet50_2(pretrained=False, progress=True, **kwargs):
|
||||
r"""Wide ResNet-50-2 model from
|
||||
`"Wide Residual Networks" <https://arxiv.org/pdf/1605.07146.pdf>`_
|
||||
|
||||
The model is the same as ResNet except for the bottleneck number of channels
|
||||
which is twice larger in every block. The number of channels in outer 1x1
|
||||
convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048
|
||||
channels, and in Wide ResNet-50-2 has 2048-1024-2048.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['width_per_group'] = 64 * 2
|
||||
return _resnet('wide_resnet50_2', Bottleneck, [3, 4, 6, 3],
|
||||
pretrained, progress, **kwargs)
|
||||
|
||||
|
||||
def wide_resnet101_2(pretrained=False, progress=True, **kwargs):
|
||||
r"""Wide ResNet-101-2 model from
|
||||
`"Wide Residual Networks" <https://arxiv.org/pdf/1605.07146.pdf>`_
|
||||
|
||||
The model is the same as ResNet except for the bottleneck number of channels
|
||||
which is twice larger in every block. The number of channels in outer 1x1
|
||||
convolutions is the same, e.g. last block in ResNet-50 has 2048-512-2048
|
||||
channels, and in Wide ResNet-50-2 has 2048-1024-2048.
|
||||
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
progress (bool): If True, displays a progress bar of the download to stderr
|
||||
"""
|
||||
kwargs['width_per_group'] = 64 * 2
|
||||
return _resnet('wide_resnet101_2', Bottleneck, [3, 4, 23, 3],
|
||||
pretrained, progress, **kwargs)
|
215
detecttracking/contrast/genfeats.py
Normal file
215
detecttracking/contrast/genfeats.py
Normal file
@ -0,0 +1,215 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Sun Nov 3 12:05:19 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
# import torch
|
||||
import pickle
|
||||
# import json
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from feat_extract.config import config as conf
|
||||
# from model import resnet18 as resnet18
|
||||
from feat_extract.inference import FeatsInterface #, inference_image
|
||||
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
|
||||
|
||||
# def model_init(conf, mpath=None):
|
||||
# '''======= 0. 配置特征提取模型地址 ======='''
|
||||
# if mpath is None:
|
||||
# model_path = conf.test_model
|
||||
# else:
|
||||
# model_path = mpath
|
||||
|
||||
# ##============ 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))
|
||||
|
||||
# return model
|
||||
|
||||
def get_std_barcodeDict(bcdpath, savepath, bcdSet):
|
||||
'''
|
||||
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
|
||||
if bcdSet is None:
|
||||
stdBarcodeList.append(filename)
|
||||
elif filename in bcdSet:
|
||||
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 = {}
|
||||
|
||||
Encoder = FeatsInterface(conf)
|
||||
|
||||
'''4处同名: (1)barcode原始图像文件夹; (2)imgPath中的 .pickle 文件名;
|
||||
(3)该pickle文件中字典的key值; (4)特征向量字典中的一个key值'''
|
||||
k = 0
|
||||
for filename in os.listdir(imgPath):
|
||||
bcd, ext = os.path.splitext(filename)
|
||||
filepath = os.path.join(imgPath, filename)
|
||||
if ext != ".pickle": continue
|
||||
if bcdSet is not None and bcd not in bcdSet:
|
||||
continue
|
||||
|
||||
featpath = os.path.join(featPath, f"{bcd}.pickle")
|
||||
if os.path.isfile(featpath):
|
||||
continue
|
||||
|
||||
stdbDict = {}
|
||||
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)
|
||||
|
||||
imgs = []
|
||||
for d, imgpath in enumerate(imgpaths):
|
||||
img = Image.open(imgpath)
|
||||
imgs.append(img)
|
||||
|
||||
feature = Encoder.inference(imgs)
|
||||
|
||||
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(featpath, '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
|
||||
|
||||
return
|
||||
|
||||
|
||||
def gen_bcd_features(imgpath, bcdpath, featpath, bcdSet=None):
|
||||
''' 生成标准特征集 '''
|
||||
'''1. 提取 imgpath 中样本地址,生成字典{barcode: [imgpath1, imgpath1, ...]}
|
||||
并存储于: bcdpath, 格式为 barcode.pickle'''
|
||||
get_std_barcodeDict(imgpath, bcdpath, bcdSet)
|
||||
|
||||
'''2. 特征提取,并保存至文件夹 featpath 中,也根据 bcdSet 交集执行'''
|
||||
stdfeat_infer(bcdpath, featpath, bcdSet)
|
||||
|
||||
def main():
|
||||
imgpath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v1.0\比对数据\整理\zhantingBase"
|
||||
bcdpath = r"D:\exhibition\dataset\bcdpath"
|
||||
featpath = r"D:\exhibition\dataset\feats"
|
||||
|
||||
|
||||
gen_bcd_features(imgpath, bcdpath, featpath)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
277
detecttracking/contrast/one2n_contrast.py
Normal file
277
detecttracking/contrast/one2n_contrast.py
Normal file
@ -0,0 +1,277 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Dec 18 11:49:01 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import pickle
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.spatial.distance import cdist
|
||||
from utils.event import ShoppingEvent
|
||||
|
||||
|
||||
def init_eventdict(sourcePath, stype="data"):
|
||||
'''stype: str,
|
||||
'source': 由 videos 或 images 生成的 pickle 文件
|
||||
'data': 从 data 文件中读取的现场运行数据
|
||||
'''
|
||||
|
||||
k, errEvents = 0, []
|
||||
for bname in os.listdir(sourcePath):
|
||||
# bname = r"20241126-135911-bdf91cf9-3e9a-426d-94e8-ddf92238e175_6923555210479"
|
||||
|
||||
source_path = os.path.join(sourcePath, bname)
|
||||
if stype=="data":
|
||||
pickpath = os.path.join(eventDataPath, f"{bname}.pickle")
|
||||
if not os.path.isdir(source_path) or os.path.isfile(pickpath):
|
||||
continue
|
||||
if stype=="source":
|
||||
pickpath = os.path.join(eventDataPath, bname)
|
||||
if not os.path.isfile(source_path) or os.path.isfile(pickpath):
|
||||
continue
|
||||
|
||||
try:
|
||||
event = ShoppingEvent(source_path, stype)
|
||||
|
||||
with open(pickpath, 'wb') as f:
|
||||
pickle.dump(event, f)
|
||||
print(bname)
|
||||
except Exception as e:
|
||||
errEvents.append(source_path)
|
||||
print(e)
|
||||
# k += 1
|
||||
# if k==1:
|
||||
# break
|
||||
|
||||
errfile = os.path.join(resultPath, 'error_events.txt')
|
||||
with open(errfile, 'a', encoding='utf-8') as f:
|
||||
for line in errEvents:
|
||||
f.write(line + '\n')
|
||||
|
||||
def read_eventdict(eventDataPath):
|
||||
evtDict = {}
|
||||
for filename in os.listdir(eventDataPath):
|
||||
evtname, ext = os.path.splitext(filename)
|
||||
if ext != ".pickle": continue
|
||||
|
||||
evtpath = os.path.join(eventDataPath, filename)
|
||||
with open(evtpath, 'rb') as f:
|
||||
evtdata = pickle.load(f)
|
||||
evtDict[evtname] = evtdata
|
||||
|
||||
|
||||
return evtDict
|
||||
|
||||
def simi_calc(event, o2nevt, typee=None):
|
||||
if typee == "11":
|
||||
boxes1 = event.front_boxes
|
||||
boxes2 = o2nevt.front_boxes
|
||||
|
||||
feat1 = event.front_feats
|
||||
feat2 = o2nevt.front_feats
|
||||
if typee == "10":
|
||||
boxes1 = event.front_boxes
|
||||
boxes2 = o2nevt.back_boxes
|
||||
|
||||
feat1 = event.front_feats
|
||||
feat2 = o2nevt.back_feats
|
||||
if typee == "00":
|
||||
boxes1 = event.back_boxes
|
||||
boxes2 = o2nevt.back_boxes
|
||||
|
||||
feat1 = event.back_feats
|
||||
feat2 = o2nevt.back_feats
|
||||
if typee == "01":
|
||||
boxes1 = event.back_boxes
|
||||
boxes2 = o2nevt.front_boxes
|
||||
|
||||
feat1 = event.back_feats
|
||||
feat2 = o2nevt.front_feats
|
||||
|
||||
'''自定义事件特征选择'''
|
||||
if typee==3:
|
||||
feat1 = event.feats_compose
|
||||
feat2 = o2nevt.feats_compose
|
||||
|
||||
|
||||
if len(feat1) and len(feat2):
|
||||
matrix = 1 - cdist(feat1[0], feat2[0], 'cosine')
|
||||
simi = np.mean(matrix)
|
||||
else:
|
||||
simi = None
|
||||
return simi
|
||||
|
||||
|
||||
def one2n_pr(evtDicts, pattern=1):
|
||||
'''
|
||||
pattern:
|
||||
1: process.data 中记录的相似度
|
||||
2: 根据 process.data 中标记的 type 选择特征计算
|
||||
3: 以其它方式选择特征计算
|
||||
'''
|
||||
|
||||
tpevents, fnevents, fpevents, tnevents = [], [], [], []
|
||||
tpsimi, fnsimi, tnsimi, fpsimi = [], [], [], []
|
||||
errorFile_one2n = []
|
||||
for evtname, event in evtDicts.items():
|
||||
evt_names, evt_barcodes, evt_similars, evt_types = [], [], [], []
|
||||
|
||||
for ndict in event.one2n:
|
||||
nname = ndict["event"]
|
||||
barcode = ndict["barcode"]
|
||||
similar = ndict["similar"]
|
||||
typee = ndict["type"].strip()
|
||||
|
||||
evt_names.append(nname)
|
||||
evt_barcodes.append(barcode)
|
||||
evt_types.append(typee)
|
||||
|
||||
if pattern==1:
|
||||
evt_similars.append(similar)
|
||||
|
||||
if pattern==2 or pattern==3:
|
||||
o2n_evt = [evt for name, evt in evtDicts.items() if name.find(nname[:15])==0]
|
||||
if len(o2n_evt)==1:
|
||||
o2nevt = o2n_evt[0]
|
||||
else:
|
||||
continue
|
||||
|
||||
if pattern==2:
|
||||
simival = simi_calc(event, o2nevt, typee)
|
||||
|
||||
if pattern==3:
|
||||
simival = simi_calc(event, o2nevt, typee=pattern)
|
||||
|
||||
if simival==None:
|
||||
continue
|
||||
evt_similars.append(simival)
|
||||
|
||||
if len(evt_names)==len(evt_barcodes) and len(evt_barcodes)==len(evt_similars) \
|
||||
and len(evt_similars)==len(evt_types) and len(evt_names)>0:
|
||||
|
||||
# maxsim = evt_similars[evt_similars.index(max(evt_similars))]
|
||||
maxsim = max(evt_similars)
|
||||
for i in range(len(evt_names)):
|
||||
bcd, simi = evt_barcodes[i], evt_similars[i]
|
||||
|
||||
if bcd==event.barcode and simi==maxsim:
|
||||
tpsimi.append(simi)
|
||||
tpevents.append(evtname)
|
||||
elif bcd==event.barcode and simi!=maxsim:
|
||||
fnsimi.append(simi)
|
||||
fnevents.append(evtname)
|
||||
elif bcd!=event.barcode and simi!=maxsim:
|
||||
tnsimi.append(simi)
|
||||
tnevents.append(evtname)
|
||||
elif bcd!=event.barcode and simi==maxsim and event.barcode in evt_barcodes:
|
||||
fpsimi.append(simi)
|
||||
fpevents.append(evtname)
|
||||
else:
|
||||
errorFile_one2n.append(evtname)
|
||||
|
||||
|
||||
|
||||
''' 1:n 数据存储,需根据相似度排序'''
|
||||
PPrecise, PRecall = [], []
|
||||
NPrecise, NRecall = [], []
|
||||
|
||||
Thresh = np.linspace(-0.2, 1, 100)
|
||||
for th in Thresh:
|
||||
'''============================= 1:n 计算'''
|
||||
TP = sum(np.array(tpsimi) >= th)
|
||||
FP = sum(np.array(fpsimi) >= th)
|
||||
FN = sum(np.array(fnsimi) < th)
|
||||
TN = sum(np.array(tnsimi) < th)
|
||||
|
||||
PPrecise.append(TP/(TP+FP+1e-6))
|
||||
PRecall.append(TP/(len(tpsimi)+len(fnsimi)+1e-6))
|
||||
NPrecise.append(TN/(TN+FN+1e-6))
|
||||
NRecall.append(TN/(len(tnsimi)+len(fpsimi)+1e-6))
|
||||
|
||||
|
||||
'''4. ============================= 1:n 曲线,'''
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, PPrecise, 'r', label='Precise_Pos: TP/TPFP')
|
||||
ax.plot(Thresh, PRecall, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, NPrecise, 'g', label='Precise_Neg: TN/TNFP')
|
||||
ax.plot(Thresh, NRecall, 'c', label='Recall_Neg: TN/TNFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('1:n Precise & Recall')
|
||||
ax.set_xlabel(f"Event Num: {len(tpsimi)+len(fnsimi)}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
## ============================= 1:n 直方图'''
|
||||
fig, axes = plt.subplots(2, 2)
|
||||
axes[0, 0].hist(tpsimi, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
axes[0, 0].set_xlim([-0.2, 1])
|
||||
axes[0, 0].set_title('TP')
|
||||
axes[0, 1].hist(fpsimi, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
axes[0, 1].set_xlim([-0.2, 1])
|
||||
axes[0, 1].set_title('FP')
|
||||
axes[1, 0].hist(tnsimi, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
axes[1, 0].set_xlim([-0.2, 1])
|
||||
axes[1, 0].set_title('TN')
|
||||
axes[1, 1].hist(fnsimi, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
axes[1, 1].set_xlim([-0.2, 1])
|
||||
axes[1, 1].set_title('FN')
|
||||
plt.show()
|
||||
|
||||
return fpevents
|
||||
|
||||
def main():
|
||||
|
||||
'''1. 生成事件字典并保存至 eventDataPath, 只需运行一次 '''
|
||||
init_eventdict(eventSourcePath, stype="source")
|
||||
|
||||
'''2. 读取事件字典 '''
|
||||
evtDicts = read_eventdict(eventDataPath)
|
||||
|
||||
|
||||
'''3. 1:n 比对事件评估 '''
|
||||
fpevents = one2n_pr(evtDicts, pattern=3)
|
||||
|
||||
fpErrFile = str(Path(resultPath).joinpath("one2n_fp_Error.txt"))
|
||||
with open(fpErrFile, "w") as file:
|
||||
for item in fpevents:
|
||||
file.write(item + "\n")
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
eventSourcePath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\ShoppingDict_pkfile"
|
||||
resultPath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\result\contrast"
|
||||
|
||||
eventDataPath = os.path.join(resultPath, "evtobjs")
|
||||
similPath = os.path.join(resultPath, "simidata")
|
||||
if not os.path.exists(eventDataPath):
|
||||
os.makedirs(eventDataPath)
|
||||
if not os.path.exists(similPath):
|
||||
os.makedirs(similPath)
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
520
detecttracking/contrast/onsite_contrast_pr.py
Normal file
520
detecttracking/contrast/onsite_contrast_pr.py
Normal file
@ -0,0 +1,520 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Sep 11 11:57:30 2024
|
||||
永辉现场试验输出数据的 1:1 性能评估
|
||||
适用于202410前数据保存版本的,需调用 OneToOneCompare.txt
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
import matplotlib.pyplot as plt
|
||||
import sys
|
||||
|
||||
sys.path.append(r"D:\DetectTracking")
|
||||
from tracking.utils.read_data import read_similar
|
||||
|
||||
def read_one2one_data(filepath):
|
||||
simiList = []
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
split_flag = False
|
||||
simi_dict = {}
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
if len(simi_dict): simiList.append(simi_dict)
|
||||
simi_dict = {}
|
||||
continue
|
||||
|
||||
label = line.split(':')[0].strip()
|
||||
value = line.split(':')[1].strip()
|
||||
|
||||
if label.find("SeqDir") >= 0:
|
||||
simi_dict["SeqDir"] = value
|
||||
if label.isdigit() and len(label) >= 8:
|
||||
|
||||
simi_max, simi_min = value.strip(',').split('.')
|
||||
simi_dict["barcode"] = label
|
||||
simi_dict["simi_max"] = float(simi_max) / 1000
|
||||
simi_dict["simi_min"] = float(simi_min) / 1000
|
||||
|
||||
if len(simi_dict): simiList.append(simi_dict)
|
||||
|
||||
return simiList
|
||||
|
||||
def plot_pr_curve(matrix):
|
||||
|
||||
simimax, simimean = [], []
|
||||
need_analysis = []
|
||||
for simidict in matrix:
|
||||
simimax.append(simidict["simi_max"])
|
||||
simimean.append(simidict["simi_min"])
|
||||
if simidict["simi_max"]>0.6:
|
||||
need_analysis.append(simidict)
|
||||
|
||||
simimax = np.array(simimax)
|
||||
simimean = np.array(simimean)
|
||||
|
||||
TPFN_max = len(simimax)
|
||||
TPFN_mean = len(simimean)
|
||||
|
||||
fig, axs = plt.subplots(2, 1)
|
||||
axs[0].hist(simimax, bins=60, edgecolor='black')
|
||||
axs[0].set_xlim([-0.2, 1])
|
||||
axs[0].set_title(f'Same Barcode, Num: {TPFN_max}')
|
||||
axs[1].hist(simimean, bins=60, edgecolor='black')
|
||||
axs[1].set_xlim([-0.2, 1])
|
||||
axs[1].set_title(f'Cross Barcode, Num: {TPFN_mean}')
|
||||
# plt.savefig(f'./result/{file}_hist.png') # svg, png, pdf
|
||||
|
||||
Recall_Neg = []
|
||||
Thresh = np.linspace(-0.2, 1, 100)
|
||||
for th in Thresh:
|
||||
TN = np.sum(simimax < th)
|
||||
Recall_Neg.append(TN/TPFN_max)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, Recall_Neg, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('Positive recall')
|
||||
ax.set_xlabel(f"Num: {TPFN_max}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
# plt.savefig(f'./result/{file}_pr.png') # svg, png, pdf
|
||||
|
||||
print("Have done!")
|
||||
pass
|
||||
|
||||
|
||||
def test_compare():
|
||||
filepaths = [r"\\192.168.1.28\share\测试_202406\0913_扫A放B\0913_1\OneToOneCompare.txt",
|
||||
r"\\192.168.1.28\share\测试_202406\0913_扫A放B\0913_2\OneToOneCompare.txt",
|
||||
r"\\192.168.1.28\share\测试_202406\0914_扫A放B\0914_1\OneToOneCompare.txt",
|
||||
r"\\192.168.1.28\share\测试_202406\0914_扫A放B\0914_2\OneToOneCompare.txt"
|
||||
]
|
||||
|
||||
simiList = []
|
||||
for fp in filepaths:
|
||||
slist = read_one2one_data(fp)
|
||||
simiList.extend(slist)
|
||||
|
||||
plot_pr_curve(simiList)
|
||||
|
||||
def contrast_pr(paths):
|
||||
'''
|
||||
1:1
|
||||
'''
|
||||
paths = Path(paths)
|
||||
|
||||
evtpaths = []
|
||||
for p in paths.iterdir():
|
||||
condt1 = p.is_dir()
|
||||
condt2 = len(p.name.split('_'))>=2
|
||||
condt3 = len(p.name.split('_')[-1])>8
|
||||
condt4 = p.name.split('_')[-1].isdigit()
|
||||
if condt1 and condt2 and condt3 and condt4:
|
||||
evtpaths.append(p)
|
||||
|
||||
# evtpaths = [p for p in paths.iterdir() if p.is_dir() and len(p.name.split('_'))>=2 and len(p.name.split('_')[-1])>8]
|
||||
# evtpaths = [p for p in paths.iterdir() if p.is_dir()]
|
||||
|
||||
events, similars = [], []
|
||||
##===================================== 扫A放A, 扫A放B场景()
|
||||
one2oneAA, one2oneAB = [], []
|
||||
one2SNAA, one2SNAB = [], []
|
||||
|
||||
##===================================== 应用于 1:1
|
||||
_tp_events, _fn_events, _fp_events, _tn_events = [], [], [], []
|
||||
_tp_simi, _fn_simi, _tn_simi, _fp_simi = [], [], [], []
|
||||
|
||||
##===================================== 应用于 1:SN
|
||||
tp_events, fn_events, fp_events, tn_events = [], [], [], []
|
||||
tp_simi, fn_simi, tn_simi, fp_simi = [], [], [], []
|
||||
|
||||
##===================================== 应用于1:n
|
||||
tpevents, fnevents, fpevents, tnevents = [], [], [], []
|
||||
tpsimi, fnsimi, tnsimi, fpsimi = [], [], [], []
|
||||
|
||||
##===================================== barcodes总数、比对错误事件
|
||||
bcdList = []
|
||||
one2onePath, one2onePath1 = [], []
|
||||
one2SNPath, one2SNPath1 = [], []
|
||||
one2nPath = []
|
||||
|
||||
errorFile_one2one, errorFile_one2SN, errorFile_one2n = [], [], []
|
||||
|
||||
for path in evtpaths:
|
||||
barcode = path.stem.split('_')[-1]
|
||||
datapath = path.joinpath('process.data')
|
||||
|
||||
if not barcode.isdigit() or len(barcode)<10: continue
|
||||
if not datapath.is_file(): continue
|
||||
|
||||
bcdList.append(barcode)
|
||||
|
||||
try:
|
||||
SimiDict = read_similar(datapath)
|
||||
except Exception as e:
|
||||
print(f"{path.stem}, Error: {e}")
|
||||
|
||||
|
||||
'''放入为 1:1,相似度取最大值;取出时为 1:SN, 相似度取均值'''
|
||||
one2one = SimiDict['one2one']
|
||||
one2SN = SimiDict['one2SN']
|
||||
one2n = SimiDict['one2n']
|
||||
|
||||
'''================== 0. 1:1 ==================='''
|
||||
barcodes, similars = [], []
|
||||
for dt in one2one:
|
||||
one2onePath.append((path.stem))
|
||||
if dt['similar']==0:
|
||||
one2onePath1.append((path.stem))
|
||||
continue
|
||||
barcodes.append(dt['barcode'])
|
||||
similars.append(dt['similar'])
|
||||
if len(barcodes)==len(similars) and len(barcodes)!=0:
|
||||
## 扫A放A, 扫A放B场景
|
||||
simAA = [similars[i] for i in range(len(barcodes)) if barcodes[i]==barcode]
|
||||
simAB = [similars[i] for i in range(len(barcodes)) if barcodes[i]!=barcode]
|
||||
|
||||
one2oneAA.extend(simAA)
|
||||
one2oneAB.extend(simAB)
|
||||
|
||||
## 相似度排序,barcode相等且排名第一为TP,适用于多的barcode相似度比较
|
||||
max_idx = similars.index(max(similars))
|
||||
max_sim = similars[max_idx]
|
||||
# max_bcd = barcodes[max_idx]
|
||||
for i in range(len(one2one)):
|
||||
bcd, simi = barcodes[i], similars[i]
|
||||
if bcd==barcode and simi==max_sim:
|
||||
_tp_simi.append(simi)
|
||||
_tp_events.append(path.stem)
|
||||
elif bcd==barcode and simi!=max_sim:
|
||||
_fn_simi.append(simi)
|
||||
_fn_events.append(path.stem)
|
||||
elif bcd!=barcode and simi!=max_sim:
|
||||
_tn_simi.append(simi)
|
||||
_tn_events.append(path.stem)
|
||||
elif bcd!=barcode and simi==max_sim and barcode in barcodes:
|
||||
_fp_simi.append(simi)
|
||||
_fp_events.append(path.stem)
|
||||
else:
|
||||
errorFile_one2one.append(path.stem)
|
||||
|
||||
|
||||
'''================== 2. 取出场景下的 1 : Small N ==================='''
|
||||
barcodes, similars = [], []
|
||||
for dt in one2SN:
|
||||
barcodes.append(dt['barcode'])
|
||||
similars.append(dt['similar'])
|
||||
|
||||
if len(barcodes)==len(similars) and len(barcodes)!=0:
|
||||
## 扫A放A, 扫A放B场景
|
||||
simAA = [similars[i] for i in range(len(barcodes)) if barcodes[i]==barcode]
|
||||
simAB = [similars[i] for i in range(len(barcodes)) if barcodes[i]!=barcode]
|
||||
|
||||
one2SNAA.extend(simAA)
|
||||
one2SNAB.extend(simAB)
|
||||
one2SNPath.append(path.stem)
|
||||
if len(simAA)==0:
|
||||
one2SNPath1.append(path.stem)
|
||||
|
||||
|
||||
## 相似度排序,barcode相等且排名第一为TP,适用于多的barcode相似度比较
|
||||
max_idx = similars.index(max(similars))
|
||||
max_sim = similars[max_idx]
|
||||
# max_bcd = barcodes[max_idx]
|
||||
for i in range(len(one2SN)):
|
||||
bcd, simi = barcodes[i], similars[i]
|
||||
if bcd==barcode and simi==max_sim:
|
||||
tp_simi.append(simi)
|
||||
tp_events.append(path.stem)
|
||||
elif bcd==barcode and simi!=max_sim:
|
||||
fn_simi.append(simi)
|
||||
fn_events.append(path.stem)
|
||||
elif bcd!=barcode and simi!=max_sim:
|
||||
tn_simi.append(simi)
|
||||
tn_events.append(path.stem)
|
||||
elif bcd!=barcode and simi==max_sim and barcode in barcodes:
|
||||
fp_simi.append(simi)
|
||||
fp_events.append(path.stem)
|
||||
else:
|
||||
errorFile_one2SN.append(path.stem)
|
||||
|
||||
|
||||
|
||||
'''===================== 3. 取出场景下的 1:n ========================'''
|
||||
events, evt_barcodes, evt_similars, evt_types = [], [], [], []
|
||||
for dt in one2n:
|
||||
events.append(dt["event"])
|
||||
evt_barcodes.append(dt["barcode"])
|
||||
evt_similars.append(dt["similar"])
|
||||
evt_types.append(dt["type"])
|
||||
|
||||
if len(events)==len(evt_barcodes) and len(evt_barcodes)==len(evt_similars) \
|
||||
and len(evt_similars)==len(evt_types) and len(events)>0:
|
||||
|
||||
one2nPath.append(path.stem)
|
||||
maxsim = evt_similars[evt_similars.index(max(evt_similars))]
|
||||
for i in range(len(one2n)):
|
||||
bcd, simi = evt_barcodes[i], evt_similars[i]
|
||||
|
||||
if bcd==barcode and simi==maxsim:
|
||||
tpsimi.append(simi)
|
||||
tpevents.append(path.stem)
|
||||
elif bcd==barcode and simi!=maxsim:
|
||||
fnsimi.append(simi)
|
||||
fnevents.append(path.stem)
|
||||
elif bcd!=barcode and simi!=maxsim:
|
||||
tnsimi.append(simi)
|
||||
tnevents.append(path.stem)
|
||||
elif bcd!=barcode and simi==maxsim and barcode in evt_barcodes:
|
||||
fpsimi.append(simi)
|
||||
fpevents.append(path.stem)
|
||||
else:
|
||||
errorFile_one2n.append(path.stem)
|
||||
|
||||
|
||||
'''命名规则:
|
||||
1:1 (max) 1:1 (max) 1:n 1:N
|
||||
_TP TP_ TP TPX
|
||||
_PPrecise PPrecise_ PPrecise PPreciseX
|
||||
tpsimi tp_simi
|
||||
'''
|
||||
|
||||
''' 1:1 数据存储, 相似度计算方式:最大值、均值'''
|
||||
_PPrecise, _PRecall = [], []
|
||||
_NPrecise, _NRecall = [], []
|
||||
PPrecise_, PRecall_ = [], []
|
||||
NPrecise_, NRecall_ = [], []
|
||||
|
||||
''' 1:SN 数据存储,需根据相似度排序'''
|
||||
PPreciseX, PRecallX = [], []
|
||||
NPreciseX, NRecallX = [], []
|
||||
|
||||
''' 1:n 数据存储,需根据相似度排序'''
|
||||
PPrecise, PRecall = [], []
|
||||
NPrecise, NRecall = [], []
|
||||
|
||||
|
||||
|
||||
Thresh = np.linspace(-0.2, 1, 100)
|
||||
for th in Thresh:
|
||||
'''(Precise, Recall) 计算方式, 若 1:1 与 1:SN 相似度选择方式相同,则可以合并'''
|
||||
'''===================================== 1:1 最大值'''
|
||||
_TP = sum(np.array(one2oneAA) >= th)
|
||||
_FP = sum(np.array(one2oneAB) >= th)
|
||||
_FN = sum(np.array(one2oneAA) < th)
|
||||
_TN = sum(np.array(one2oneAB) < th)
|
||||
|
||||
_PPrecise.append(_TP/(_TP+_FP+1e-6))
|
||||
_PRecall.append(_TP/(len(one2oneAA)+1e-6))
|
||||
_NPrecise.append(_TN/(_TN+_FN+1e-6))
|
||||
_NRecall.append(_TN/(len(one2oneAB)+1e-6))
|
||||
|
||||
'''===================================== 1:SN 均值'''
|
||||
TP_ = sum(np.array(one2SNAA) >= th)
|
||||
FP_ = sum(np.array(one2SNAB) >= th)
|
||||
FN_ = sum(np.array(one2SNAA) < th)
|
||||
TN_ = sum(np.array(one2SNAB) < th)
|
||||
|
||||
PPrecise_.append(TP_/(TP_+FP_+1e-6))
|
||||
PRecall_.append(TP_/(len(one2SNAA)+1e-6))
|
||||
NPrecise_.append(TN_/(TN_+FN_+1e-6))
|
||||
NRecall_.append(TN_/(len(one2SNAB)+1e-6))
|
||||
|
||||
'''适用于 (Precise, Recall) 计算方式:多个相似度计算并排序,barcode相等且排名第一为 TP '''
|
||||
'''===================================== 1:SN '''
|
||||
TPX = sum(np.array(tp_simi) >= th)
|
||||
FPX = sum(np.array(fp_simi) >= th)
|
||||
FNX = sum(np.array(fn_simi) < th)
|
||||
TNX = sum(np.array(tn_simi) < th)
|
||||
PPreciseX.append(TPX/(TPX+FPX+1e-6))
|
||||
PRecallX.append(TPX/(len(tp_simi)+len(fn_simi)+1e-6))
|
||||
|
||||
NPreciseX.append(TNX/(TNX+FNX+1e-6))
|
||||
NRecallX.append(TNX/(len(tn_simi)+len(fp_simi)+1e-6))
|
||||
|
||||
|
||||
'''===================================== 1:n'''
|
||||
TP = sum(np.array(tpsimi) >= th)
|
||||
FP = sum(np.array(fpsimi) >= th)
|
||||
FN = sum(np.array(fnsimi) < th)
|
||||
TN = sum(np.array(tnsimi) < th)
|
||||
|
||||
PPrecise.append(TP/(TP+FP+1e-6))
|
||||
PRecall.append(TP/(len(tpsimi)+len(fnsimi)+1e-6))
|
||||
NPrecise.append(TN/(TN+FN+1e-6))
|
||||
NRecall.append(TN/(len(tnsimi)+len(fpsimi)+1e-6))
|
||||
|
||||
|
||||
|
||||
|
||||
'''1. ============================= 1:1 最大值方案 曲线'''
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, _PPrecise, 'r', label='Precise_Pos: TP/TPFP')
|
||||
ax.plot(Thresh, _PRecall, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, _NPrecise, 'g', label='Precise_Neg: TN/TNFP')
|
||||
ax.plot(Thresh, _NRecall, 'c', label='Recall_Neg: TN/TNFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('1:1 Precise & Recall')
|
||||
ax.set_xlabel(f"Event Num: {len(one2oneAA)+len(one2oneAB)}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
## ============================= 1:1 最大值方案 直方图'''
|
||||
fig, axes = plt.subplots(2, 1)
|
||||
axes[0].hist(np.array(one2oneAA), bins=60, edgecolor='black')
|
||||
axes[0].set_xlim([-0.2, 1])
|
||||
axes[0].set_title('AA')
|
||||
axes[1].hist(np.array(one2oneAB), bins=60, edgecolor='black')
|
||||
axes[1].set_xlim([-0.2, 1])
|
||||
axes[1].set_title('BB')
|
||||
plt.show()
|
||||
|
||||
|
||||
|
||||
|
||||
'''2. ============================= 1:1 均值方案 曲线'''
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, PPrecise_, 'r', label='Precise_Pos: TP/TPFP')
|
||||
ax.plot(Thresh, PRecall_, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, NPrecise_, 'g', label='Precise_Neg: TN/TNFP')
|
||||
ax.plot(Thresh, NRecall_, 'c', label='Recall_Neg: TN/TNFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('1:1 Precise & Recall')
|
||||
ax.set_xlabel(f"Event Num: {len(one2SNAA)}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
## ============================= 1:1 均值方案 直方图'''
|
||||
fig, axes = plt.subplots(2, 1)
|
||||
axes[0].hist(np.array(one2SNAA), bins=60, edgecolor='black')
|
||||
axes[0].set_xlim([-0.2, 1])
|
||||
axes[0].set_title('AA')
|
||||
axes[0].set_xlabel(f"Event Num: {len(one2SNAA)}")
|
||||
|
||||
axes[1].hist(np.array(one2SNAB), bins=60, edgecolor='black')
|
||||
axes[1].set_xlim([-0.2, 1])
|
||||
axes[1].set_title('BB')
|
||||
axes[1].set_xlabel(f"Event Num: {len(one2SNAB)}")
|
||||
plt.show()
|
||||
|
||||
''''3. ============================= 1:SN 曲线'''
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, PPreciseX, 'r', label='Precise_Pos: TP/TPFP')
|
||||
ax.plot(Thresh, PRecallX, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, NPreciseX, 'g', label='Precise_Neg: TN/TNFP')
|
||||
ax.plot(Thresh, NRecallX, 'c', label='Recall_Neg: TN/TNFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('1:SN Precise & Recall')
|
||||
ax.set_xlabel(f"Event Num: {len(one2SNAA)}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
## ============================= 1:N 展厅 直方图'''
|
||||
fig, axes = plt.subplots(2, 2)
|
||||
axes[0, 0].hist(tp_simi, bins=60, edgecolor='black')
|
||||
axes[0, 0].set_xlim([-0.2, 1])
|
||||
axes[0, 0].set_title(f'TP({len(tp_simi)})')
|
||||
axes[0, 1].hist(fp_simi, bins=60, edgecolor='black')
|
||||
axes[0, 1].set_xlim([-0.2, 1])
|
||||
axes[0, 1].set_title(f'FP({len(fp_simi)})')
|
||||
axes[1, 0].hist(tn_simi, bins=60, edgecolor='black')
|
||||
axes[1, 0].set_xlim([-0.2, 1])
|
||||
axes[1, 0].set_title(f'TN({len(tn_simi)})')
|
||||
axes[1, 1].hist(fn_simi, bins=60, edgecolor='black')
|
||||
axes[1, 1].set_xlim([-0.2, 1])
|
||||
axes[1, 1].set_title(f'FN({len(fn_simi)})')
|
||||
plt.show()
|
||||
|
||||
|
||||
'''4. ============================= 1:n 曲线,'''
|
||||
fig, ax = plt.subplots()
|
||||
ax.plot(Thresh, PPrecise, 'r', label='Precise_Pos: TP/TPFP')
|
||||
ax.plot(Thresh, PRecall, 'b', label='Recall_Pos: TP/TPFN')
|
||||
ax.plot(Thresh, NPrecise, 'g', label='Precise_Neg: TN/TNFP')
|
||||
ax.plot(Thresh, NRecall, 'c', label='Recall_Neg: TN/TNFN')
|
||||
ax.set_xlim([0, 1])
|
||||
ax.set_ylim([0, 1])
|
||||
ax.grid(True)
|
||||
ax.set_title('1:n Precise & Recall')
|
||||
ax.set_xlabel(f"Event Num: {len(tpsimi)+len(fnsimi)}")
|
||||
ax.legend()
|
||||
plt.show()
|
||||
## ============================= 1:n 直方图'''
|
||||
fig, axes = plt.subplots(2, 2)
|
||||
axes[0, 0].hist(tpsimi, bins=60, edgecolor='black')
|
||||
axes[0, 0].set_xlim([-0.2, 1])
|
||||
axes[0, 0].set_title(f'TP({len(tpsimi)})')
|
||||
axes[0, 1].hist(fpsimi, bins=60, edgecolor='black')
|
||||
axes[0, 1].set_xlim([-0.2, 1])
|
||||
axes[0, 1].set_title(f'FP({len(fpsimi)})')
|
||||
axes[1, 0].hist(tnsimi, bins=60, edgecolor='black')
|
||||
axes[1, 0].set_xlim([-0.2, 1])
|
||||
axes[1, 0].set_title(f'TN({len(tnsimi)})')
|
||||
axes[1, 1].hist(fnsimi, bins=60, edgecolor='black')
|
||||
axes[1, 1].set_xlim([-0.2, 1])
|
||||
axes[1, 1].set_title(f'FN({len(fnsimi)})')
|
||||
plt.show()
|
||||
|
||||
|
||||
fpsnErrFile = str(paths.joinpath("one2SN_Error.txt"))
|
||||
with open(fpsnErrFile, "w") as file:
|
||||
for item in fp_events:
|
||||
file.write(item + "\n")
|
||||
|
||||
fpErrFile = str(paths.joinpath("one2n_Error.txt"))
|
||||
with open(fpErrFile, "w") as file:
|
||||
for item in fpevents:
|
||||
file.write(item + "\n")
|
||||
|
||||
|
||||
|
||||
|
||||
# bcdSet = set(bcdList)
|
||||
# one2nErrFile = str(paths.joinpath("one_2_Small_n_Error.txt"))
|
||||
# with open(one2nErrFile, "w") as file:
|
||||
# for item in fnevents:
|
||||
# file.write(item + "\n")
|
||||
|
||||
# one2NErrFile = str(paths.joinpath("one_2_Big_N_Error.txt"))
|
||||
# with open(one2NErrFile, "w") as file:
|
||||
# for item in fn_events:
|
||||
# file.write(item + "\n")
|
||||
|
||||
print('Done!')
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
evtpaths = r"D:\全实时\source_data\2024122416"
|
||||
contrast_pr(evtpaths)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
109
detecttracking/contrast/select_subimgs.py
Normal file
109
detecttracking/contrast/select_subimgs.py
Normal file
@ -0,0 +1,109 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Dec 23 13:58:13 2024
|
||||
|
||||
writting for selectting std subimgs to Wuhuaqi
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
# import torch
|
||||
import pickle
|
||||
# import json
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.spatial.distance import cdist
|
||||
from feat_extract.config import config as conf
|
||||
# from model import resnet18 as resnet18
|
||||
from feat_extract.inference import FeatsInterface #, inference_image
|
||||
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
|
||||
|
||||
|
||||
|
||||
def gen_features(imgpath):
|
||||
|
||||
Encoder = FeatsInterface(conf)
|
||||
imgs, imgnames = [], []
|
||||
for filename in os.listdir(imgpath):
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext not in IMG_FORMAT: continue
|
||||
|
||||
fpath = os.path.join(imgpath, filename)
|
||||
img = Image.open(fpath)
|
||||
|
||||
imgs.append(img)
|
||||
|
||||
filelist = file.split("_")
|
||||
newname = "_".join([filelist[0],filelist[1], filelist[2], filelist[-3], filelist[-2], filelist[-1]])
|
||||
# imgnames.append(newname)
|
||||
imgnames.append(file)
|
||||
|
||||
features = Encoder.inference(imgs)
|
||||
features /= np.linalg.norm(features, axis=1)[:, None]
|
||||
|
||||
return features, imgnames
|
||||
|
||||
def top_p_percent_indices(matrix, p):
|
||||
"""
|
||||
Finds the indices of the top p% largest elements in a 2D matrix.
|
||||
Args:
|
||||
matrix (np.ndarray): A 2D NumPy array.
|
||||
p: int, 0-100
|
||||
Returns:
|
||||
List[Tuple[int, int]]: A list of indices (row, column) for the top 10% largest elements.
|
||||
"""
|
||||
# Flatten the matrix
|
||||
flat_matrix = matrix.flatten()
|
||||
|
||||
# Calculate the threshold for the top 10%
|
||||
num_elements = len(flat_matrix)
|
||||
threshold_index = int(num_elements * 0.01*p) # Top 10%
|
||||
threshold_index = max(1, threshold_index) # Ensure at least one element is considered
|
||||
threshold_value = np.partition(flat_matrix, -threshold_index)[-threshold_index]
|
||||
|
||||
# Create a mask for elements >= threshold
|
||||
mask = matrix >= threshold_value
|
||||
|
||||
# Get the indices of elements that satisfy the mask
|
||||
indices = np.argwhere(mask)
|
||||
|
||||
return list(map(tuple, indices))
|
||||
|
||||
|
||||
def main():
|
||||
imgpath = r"\\192.168.1.28\share\数据\已完成数据\展厅数据\v1.0\比对数据\整理\zhantingBase\6923555210479"
|
||||
|
||||
feats, imgnames = gen_features(imgpath)
|
||||
n = len(feats)
|
||||
|
||||
matrix = 1 - cdist(feats, feats, 'cosine')
|
||||
|
||||
nmatrix = np.array([[matrix[i][j] for j in range(n) if i != j] for i in range(n)])
|
||||
|
||||
top_p_large_index = top_p_percent_indices(nmatrix, 1)
|
||||
top_p_small_index = top_p_percent_indices(-1*nmatrix, 1)
|
||||
|
||||
simi_mean = np.mean(nmatrix, axis=1)
|
||||
max_simi = np.max(nmatrix)
|
||||
max_index = np.where(nmatrix==max_simi)
|
||||
min_simi = np.min(nmatrix)
|
||||
min_index = np.where(nmatrix==min_simi)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
|
||||
simils = [matrix[i][j] for j in range(n) for i in range(n) if j>i]
|
||||
ax.hist(simils, bins=60, range=(-0.2, 1), edgecolor='black')
|
||||
ax.set_xlim([-0.2, 1])
|
||||
ax.set_title("Similarity")
|
||||
|
||||
|
||||
print("done!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
200
detecttracking/contrast/seqfeat_compare.py
Normal file
200
detecttracking/contrast/seqfeat_compare.py
Normal file
@ -0,0 +1,200 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Fri Aug 9 10:36:45 2024
|
||||
分析图像对间的相似度
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
import torch
|
||||
import sys
|
||||
from scipy.spatial.distance import cdist
|
||||
|
||||
''' 加载 LC 定义的模型形式'''
|
||||
from config import config as conf
|
||||
from model import resnet18 as resnet18
|
||||
from test_ori import inference_image
|
||||
##============ load resnet mdoel
|
||||
model = resnet18().to(conf.device)
|
||||
# model = nn.DataParallel(model).to(conf.device)
|
||||
model.load_state_dict(torch.load(conf.test_model, map_location=conf.device))
|
||||
model.eval()
|
||||
print('load model {} '.format(conf.testbackbone))
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.JPG', '.jpeg', '.png']
|
||||
|
||||
# =============================================================================
|
||||
# ''' 加载REID中定义的模型形式'''
|
||||
# sys.path.append(r"D:\DetectTracking")
|
||||
# from tracking.trackers.reid.reid_interface import ReIDInterface
|
||||
# from tracking.trackers.reid.config import config as ReIDConfig
|
||||
# ReIDEncoder = ReIDInterface(ReIDConfig)
|
||||
#
|
||||
# def inference_image_ReID(images):
|
||||
# batch_patches = []
|
||||
# patches = []
|
||||
# for d, img1 in enumerate(images):
|
||||
#
|
||||
#
|
||||
# img = img1[:, :, ::-1].copy() # the model expects RGB inputs
|
||||
# patch = ReIDEncoder.transform(img)
|
||||
#
|
||||
# # 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 features
|
||||
# =============================================================================
|
||||
|
||||
|
||||
def silimarity_compare():
|
||||
|
||||
imgpaths = r"D:\DetectTracking\contrast\images\2"
|
||||
|
||||
|
||||
filepaths = []
|
||||
for root, dirs, filenames in os.walk(imgpaths):
|
||||
for filename in filenames:
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext not in IMG_FORMAT: continue
|
||||
|
||||
file_path = os.path.join(root, filename)
|
||||
filepaths.append(file_path)
|
||||
|
||||
feature = inference_image(filepaths, conf.test_transform, model, conf.device)
|
||||
feature /= np.linalg.norm(feature, axis=1)[:, None]
|
||||
|
||||
similar = 1 - np.maximum(0.0, cdist(feature, feature, metric='cosine'))
|
||||
|
||||
|
||||
print("Done!")
|
||||
|
||||
|
||||
|
||||
def similarity_compare_sequence(root_dir):
|
||||
'''
|
||||
root_dir:包含 "subimgs"字段的文件夹中图像为 subimg子图
|
||||
功能:相邻帧子图间相似度比较
|
||||
|
||||
|
||||
'''
|
||||
|
||||
all_files = []
|
||||
extensions = ['.png', '.jpg']
|
||||
for dirpath, dirnames, filenames in os.walk(root_dir):
|
||||
filepaths = []
|
||||
for filename in filenames:
|
||||
if os.path.basename(dirpath).find('subimgs') < 0:
|
||||
continue
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext in extensions:
|
||||
imgpath = os.path.join(dirpath, filename)
|
||||
filepaths.append(imgpath)
|
||||
nf = len(filepaths)
|
||||
if nf==0:
|
||||
continue
|
||||
|
||||
fnma = os.path.basename(filepaths[0]).split('.')[0]
|
||||
imga = cv2.imread(filepaths[0])
|
||||
ha, wa = imga.shape[:2]
|
||||
|
||||
for i in range(1, nf):
|
||||
fnmb = os.path.basename(filepaths[i]).split('.')[0]
|
||||
|
||||
imgb = cv2.imread(filepaths[i])
|
||||
hb, wb = imgb.shape[:2]
|
||||
|
||||
|
||||
feats = inference_image_ReID(((imga, imgb)))
|
||||
|
||||
similar = 1 - np.maximum(0.0, cdist(feats, feats, metric='cosine'))
|
||||
|
||||
|
||||
h, w = max((ha, hb)), max((wa, wb))
|
||||
img = np.zeros(((h, 2*w, 3)), np.uint8)
|
||||
img[0:ha, 0:wa], img[0:hb, w:(w+wb)] = imga, imgb
|
||||
|
||||
linewidth = max(round(((h+2*w))/2 * 0.001), 2)
|
||||
cv2.putText(img,
|
||||
text=f'{similar[0,1]:.2f}', # Text string to be drawn
|
||||
org=(max(w-20, 10), h-10), # Bottom-left corner of the text string
|
||||
fontFace=0, # Font type
|
||||
fontScale=linewidth/3, # Font scale factor
|
||||
color=(0, 0, 255), # Text color
|
||||
thickness=linewidth, # Thickness of the lines used to draw a text
|
||||
lineType=cv2.LINE_AA, # Line type
|
||||
)
|
||||
spath = os.path.join(dirpath, 's'+fnma+'-vs-'+fnmb+'.png')
|
||||
cv2.imwrite(spath, img)
|
||||
|
||||
|
||||
fnma = os.path.basename(filepaths[i]).split('.')[0]
|
||||
imga = imgb.copy()
|
||||
ha, wa = imga.shape[:2]
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
def main():
|
||||
root_dir = r"D:\contrast\dataset\result\20240723-112242_6923790709882"
|
||||
|
||||
try:
|
||||
similarity_compare_sequence(root_dir)
|
||||
except Exception as e:
|
||||
print(f'Error: {e}')
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
|
||||
silimarity_compare()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
160
detecttracking/contrast/stdfeat_analys.py
Normal file
160
detecttracking/contrast/stdfeat_analys.py
Normal file
@ -0,0 +1,160 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Wed Nov 20 11:17:29 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
||||
import os
|
||||
import cv2
|
||||
import pickle
|
||||
import numpy as np
|
||||
from scipy.spatial.distance import cdist
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def save_imgpairs(barcode, imgpaths, matrix, savepath, thresh=(0.4, 0.6), ctype="intra"):
|
||||
if ctype=="intra":
|
||||
rows, cols = np.triu_indices(matrix.shape[0], k=1) # k=1 表示不包括对角线
|
||||
mask = matrix[rows, cols] < thresh[1]
|
||||
indices = list(zip(rows[mask], cols[mask]))
|
||||
else:
|
||||
rows, cols = np.where(matrix > thresh[0])
|
||||
indices = list(zip(rows, cols))
|
||||
|
||||
|
||||
if len(indices):
|
||||
savepath = os.path.join(savepath, barcode)
|
||||
if not os.path.exists(savepath):
|
||||
os.makedirs (savepath)
|
||||
|
||||
|
||||
for idx1, idx2 in indices:
|
||||
if len(imgpaths) == 1:
|
||||
img1 = cv2.imread(imgpaths[0][idx1])
|
||||
img2 = cv2.imread(imgpaths[0][idx2])
|
||||
elif len(imgpaths) == 2:
|
||||
img1 = cv2.imread(imgpaths[0][idx1])
|
||||
img2 = cv2.imread(imgpaths[1][idx2])
|
||||
|
||||
|
||||
|
||||
simi = matrix[idx1, idx2]
|
||||
|
||||
H1, W1 = img1.shape[:2]
|
||||
H2, W2 = img2.shape[:2]
|
||||
H, W = max((H1, H2)), max((W1, W2))
|
||||
img = np.ones((H, 2*W, 3), dtype=np.uint8) *np.array([255, 128, 128])
|
||||
|
||||
img[0:H1, 0:W1, :] = img1
|
||||
img[0:H2, (2*W-W2):, :] = img2
|
||||
|
||||
text = f"sim: {simi:.2f}"
|
||||
org = (10, H-10)
|
||||
cv2.putText(img, text, org, fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.75,
|
||||
color=(0, 0, 255), thickness=2, lineType=cv2.LINE_AA)
|
||||
imgpath = os.path.join(savepath, f"{simi:.2f}_{barcode}_{idx1}_{idx2}.png")
|
||||
cv2.imwrite(imgpath, img)
|
||||
|
||||
|
||||
|
||||
def feat_analysis(featpath):
|
||||
savepath = r"D:\exhibition\result\stdfeat"
|
||||
|
||||
InterThresh = (0.4, 0.6)
|
||||
|
||||
featDict, features= [], []
|
||||
for filename in os.listdir(featpath):
|
||||
file, ext = os.path.splitext(filename)
|
||||
if ext != ".pickle": continue
|
||||
|
||||
filepath = os.path.join(featpath, filename)
|
||||
with open(filepath, 'rb') as f:
|
||||
bpDict = pickle.load(f)
|
||||
|
||||
feat = bpDict["feats_ft32"]
|
||||
|
||||
featDict.append(bpDict)
|
||||
features.append(feat)
|
||||
N = len(features)
|
||||
|
||||
simMatrix = []
|
||||
intra_simi = np.empty(0)
|
||||
low_simi_index = {}
|
||||
for i, feats in enumerate(features):
|
||||
matrix = 1 - cdist(feats, feats, 'cosine')
|
||||
|
||||
simMatrix.append(matrix)
|
||||
|
||||
'''提取相似矩阵上三角元素'''
|
||||
rows, cols = np.triu_indices(matrix.shape[0], k=1) # k=1 表示不包括对角线
|
||||
upper_tri= matrix[rows, cols]
|
||||
intra_simi = np.concatenate((intra_simi, upper_tri))
|
||||
|
||||
'''保存相似度小于阈值的图像对'''
|
||||
barcode = featDict[i]["barcode"]
|
||||
imgpaths = featDict[i]["imgpaths"]
|
||||
# save_imgpairs(barcode, [imgpaths], matrix, savepath, InterThresh, "intra")
|
||||
print(f"{barcode} have done!")
|
||||
|
||||
Matrix = np.zeros((N, N))
|
||||
inter_bcds = []
|
||||
inter_simi = np.empty(0)
|
||||
for i, feati in enumerate(features):
|
||||
bcdi = featDict[i]["barcode"]
|
||||
imgpathi = featDict[i]["imgpaths"]
|
||||
for j, featj in enumerate(features):
|
||||
bcdj = featDict[j]["barcode"]
|
||||
imgpathj = featDict[j]["imgpaths"]
|
||||
|
||||
matrix = 1 - cdist(feati, featj, 'cosine')
|
||||
|
||||
inter_bcds.append((i, j, bcdi, bcdj))
|
||||
Matrix[i, j] = np.mean(matrix)
|
||||
if j>i:
|
||||
bcd_ij = bcdi+'_'+bcdj
|
||||
# save_imgpairs(bcd_ij, [imgpathi, imgpathj], matrix, savepath, InterThresh, "inter")
|
||||
inter_simi = np.concatenate((inter_simi, matrix.ravel()))
|
||||
|
||||
print(f"{bcd_ij} have done!")
|
||||
|
||||
fig, axs = plt.subplots(2, 1)
|
||||
axs[0].hist(intra_simi, bins=100, color='blue', edgecolor='black', alpha=0.7)
|
||||
axs[0].set_xlim(0, 1)
|
||||
axs[0].set_xlabel('Performance')
|
||||
axs[0].set_title("inter similarity")
|
||||
|
||||
axs[1].hist(inter_simi, bins=100, color='green', edgecolor='black', alpha=0.7)
|
||||
axs[1].set_xlim(0, 1)
|
||||
axs[1].set_xlabel('Performance')
|
||||
axs[1].set_title("inter similarity")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
print("Done!")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
stdpath = r"D:\exhibition\dataset\feats"
|
||||
|
||||
feat_analysis(stdpath)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
7
detecttracking/contrast/utils/__init__.py
Normal file
7
detecttracking/contrast/utils/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Thu Sep 26 08:53:58 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
|
83
detecttracking/contrast/utils/barcode_set_operate.py
Normal file
83
detecttracking/contrast/utils/barcode_set_operate.py
Normal file
@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Fri Sep 13 16:49:05 2024
|
||||
|
||||
比较 stdBcdpath 和 filepath 中的 barcodes 列表,求出二者的并集和为包含在
|
||||
stdBcdpath 中的 barcodes 清单
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
from openpyxl import load_workbook, Workbook
|
||||
|
||||
def read_xlsx():
|
||||
stdBcdpath = r"\\192.168.1.28\share\已标注数据备份\对比数据\barcode\total_barcode_6588"
|
||||
filepath = r"\\192.168.1.28\share\联华中环店\中环店商品信息.xlsx"
|
||||
|
||||
existingPath = r'\\192.168.1.28\share\联华中环店\中环店商品信息_已有商品.xlsx'
|
||||
lackingPath = r'\\192.168.1.28\share\联华中环店\中环店商品信息_未包含商品.xlsx'
|
||||
|
||||
workbook = load_workbook(filename=filepath)
|
||||
sheet = workbook['Sheet1']
|
||||
barcodeCol = [sheet.cell(row=r, column=1).value for r in range(1, sheet.max_row+1)]
|
||||
|
||||
zhBarcodeList = [barcodeCol[i] for i in range(1, len(barcodeCol))]
|
||||
|
||||
stdBarcodeList = []
|
||||
for filename in os.listdir(stdBcdpath):
|
||||
filepath = os.path.join(stdBcdpath, filename)
|
||||
if not os.path.isdir(filepath) or not filename.isdigit():
|
||||
continue
|
||||
stdBarcodeList.append(int(filename))
|
||||
|
||||
|
||||
stdBarcodeSet = set(stdBarcodeList)
|
||||
zhBarcodeSet = set(zhBarcodeList)
|
||||
interBarcodes = list(zhBarcodeSet.intersection(stdBarcodeSet))
|
||||
|
||||
print(len(interBarcodes))
|
||||
|
||||
dest_wb1 = Workbook()
|
||||
dest_sheet1 = dest_wb1.active
|
||||
for row in sheet.iter_rows(min_row=1, max_col=sheet.max_column, values_only=True):
|
||||
if str(row[0]).find("商品条码")>=0:
|
||||
dest_sheet1.append(row)
|
||||
|
||||
if row[0] in interBarcodes:
|
||||
dest_sheet1.append(row)
|
||||
|
||||
dest_wb1.save(filename=existingPath)
|
||||
dest_wb1.close()
|
||||
|
||||
|
||||
diffBarcodes = list(zhBarcodeSet.difference(stdBarcodeSet))
|
||||
|
||||
dest_wb2 = Workbook()
|
||||
dest_sheet2 = dest_wb2.active
|
||||
for row in sheet.iter_rows(min_row=1, max_col=sheet.max_column, values_only=True):
|
||||
if str(row[0]).find("商品条码")>=0:
|
||||
dest_sheet2.append(row)
|
||||
|
||||
if row[0] in diffBarcodes:
|
||||
dest_sheet2.append(row)
|
||||
|
||||
dest_wb2.save(filename=lackingPath)
|
||||
dest_wb2.close()
|
||||
|
||||
|
||||
workbook.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# main()
|
||||
|
||||
read_xlsx()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
155
detecttracking/contrast/utils/dotest.py
Normal file
155
detecttracking/contrast/utils/dotest.py
Normal file
@ -0,0 +1,155 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Dec 10 14:30:16 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import numpy as np
|
||||
sys.path.append(r"D:\DetectTracking")
|
||||
from tracking.utils.read_data import read_tracking_output, read_similar #, extract_data, read_deletedBarcode_file
|
||||
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
|
||||
|
||||
|
||||
def creat_shopping_event(eventPath):
|
||||
'''构造放入商品事件字典,这些事件需满足条件:
|
||||
1) 前后摄至少有一条轨迹输出
|
||||
2) 保存有帧图像,以便裁剪出 boxe 子图
|
||||
'''
|
||||
|
||||
'''evtName 为一次购物事件'''
|
||||
evtName = os.path.basename(eventPath)
|
||||
evtList = evtName.split('_')
|
||||
|
||||
'''================ 0. 检查 evtName 及 eventPath 正确性和有效性 ================'''
|
||||
if evtName.find('2024')<0 and len(evtList[0])!=15:
|
||||
return
|
||||
if not os.path.isdir(eventPath):
|
||||
return
|
||||
|
||||
if len(evtList)==1 or (len(evtList)==2 and len(evtList[1])==0):
|
||||
barcode = ''
|
||||
else:
|
||||
barcode = evtList[-1]
|
||||
|
||||
if len(evtList)==3 and evtList[-1]== evtList[-2]:
|
||||
evtType = 'input'
|
||||
else:
|
||||
evtType = 'other'
|
||||
|
||||
'''================ 1. 构造事件描述字典,暂定 9 items ==============='''
|
||||
|
||||
|
||||
|
||||
|
||||
event = {}
|
||||
event['barcode'] = barcode
|
||||
event['type'] = evtType
|
||||
event['filepath'] = eventPath
|
||||
event['back_imgpaths'] = []
|
||||
event['front_imgpaths'] = []
|
||||
event['back_boxes'] = np.empty((0, 9), dtype=np.float64)
|
||||
event['front_boxes'] = np.empty((0, 9), dtype=np.float64)
|
||||
event['back_feats'] = np.empty((0, 256), dtype=np.float64)
|
||||
event['front_feats'] = np.empty((0, 256), dtype=np.float64)
|
||||
event['feats_compose'] = np.empty((0, 256), dtype=np.float64)
|
||||
event['one2one'] = None
|
||||
event['one2n'] = None
|
||||
event['feats_select'] = np.empty((0, 256), dtype=np.float64)
|
||||
|
||||
|
||||
'''================= 2. 读取 data 文件 ============================='''
|
||||
for dataname in os.listdir(eventPath):
|
||||
# filename = '1_track.data'
|
||||
datapath = os.path.join(eventPath, dataname)
|
||||
if not os.path.isfile(datapath): continue
|
||||
|
||||
CamerType = dataname.split('_')[0]
|
||||
''' 2.1 读取 0/1_track.data 中数据,暂不考虑'''
|
||||
# if dataname.find("_track.data")>0:
|
||||
# bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict = extract_data(datapath)
|
||||
|
||||
''' 2.2 读取 0/1_tracking_output.data 中数据'''
|
||||
if dataname.find("_tracking_output.data")>0:
|
||||
tracking_output_boxes, tracking_output_feats = read_tracking_output(datapath)
|
||||
if len(tracking_output_boxes) != len(tracking_output_feats): continue
|
||||
if CamerType == '0':
|
||||
event['back_boxes'] = tracking_output_boxes
|
||||
event['back_feats'] = tracking_output_feats
|
||||
elif CamerType == '1':
|
||||
event['front_boxes'] = tracking_output_boxes
|
||||
event['front_feats'] = tracking_output_feats
|
||||
|
||||
if dataname.find("process.data")==0:
|
||||
simiDict = read_similar(datapath)
|
||||
event['one2one'] = simiDict['one2one']
|
||||
event['one2n'] = simiDict['one2n']
|
||||
|
||||
|
||||
if len(event['back_boxes'])==0 or len(event['front_boxes'])==0:
|
||||
return None
|
||||
|
||||
'''2.3 事件的特征表征方式: 特征选择、特征集成'''
|
||||
bk_feats = event['back_feats']
|
||||
ft_feats = event['front_feats']
|
||||
|
||||
'''2.3.1 特征集成'''
|
||||
feats_compose = np.empty((0, 256), dtype=np.float64)
|
||||
if len(ft_feats):
|
||||
feats_compose = np.concatenate((feats_compose, ft_feats), axis=0)
|
||||
if len(bk_feats):
|
||||
feats_compose = np.concatenate((feats_compose, bk_feats), axis=0)
|
||||
event['feats_compose'] = feats_compose
|
||||
|
||||
'''2.3.1 特征选择'''
|
||||
if len(ft_feats):
|
||||
event['feats_select'] = ft_feats
|
||||
|
||||
|
||||
'''================ 3. 读取图像文件地址,并按照帧ID排序 ============='''
|
||||
frontImgs, frontFid = [], []
|
||||
backImgs, backFid = [], []
|
||||
for imgname in os.listdir(eventPath):
|
||||
name, ext = os.path.splitext(imgname)
|
||||
if ext not in IMG_FORMAT or name.find('frameId')<0: continue
|
||||
|
||||
CamerType = name.split('_')[0]
|
||||
frameId = int(name.split('_')[3])
|
||||
imgpath = os.path.join(eventPath, imgname)
|
||||
if CamerType == '0':
|
||||
backImgs.append(imgpath)
|
||||
backFid.append(frameId)
|
||||
if CamerType == '1':
|
||||
frontImgs.append(imgpath)
|
||||
frontFid.append(frameId)
|
||||
|
||||
frontIdx = np.argsort(np.array(frontFid))
|
||||
backIdx = np.argsort(np.array(backFid))
|
||||
|
||||
'''3.1 生成依据帧 ID 排序的前后摄图像地址列表'''
|
||||
frontImgs = [frontImgs[i] for i in frontIdx]
|
||||
backImgs = [backImgs[i] for i in backIdx]
|
||||
|
||||
'''3.2 将前、后摄图像路径添加至事件字典'''
|
||||
|
||||
|
||||
bfid = event['back_boxes'][:, 7].astype(np.int64)
|
||||
ffid = event['front_boxes'][:, 7].astype(np.int64)
|
||||
if len(bfid) and max(bfid) <= len(backImgs):
|
||||
event['back_imgpaths'] = [backImgs[i-1] for i in bfid]
|
||||
if len(ffid) and max(ffid) <= len(frontImgs):
|
||||
event['front_imgpaths'] = [frontImgs[i-1] for i in ffid]
|
||||
|
||||
|
||||
'''================ 4. 判断当前事件有效性,并添加至事件列表 =========='''
|
||||
condt1 = len(event['back_imgpaths'])==0 or len(event['front_imgpaths'])==0
|
||||
condt2 = len(event['front_feats'])==0 and len(event['back_feats'])==0
|
||||
|
||||
if condt1 or condt2:
|
||||
print(f"Event: {evtName}, Error, condt1: {condt1}, condt2: {condt2}")
|
||||
return None
|
||||
|
||||
return event
|
533
detecttracking/contrast/utils/event.py
Normal file
533
detecttracking/contrast/utils/event.py
Normal file
@ -0,0 +1,533 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Tue Nov 26 17:35:05 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import os
|
||||
import cv2
|
||||
import pickle
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
|
||||
import sys
|
||||
sys.path.append(r"D:\DetectTracking")
|
||||
from tracking.utils.plotting import Annotator, colors
|
||||
from tracking.utils.drawtracks import drawTrack
|
||||
from tracking.utils.read_data import extract_data, read_tracking_output, read_similar
|
||||
from tracking.utils.read_data import extract_data_realtime, read_tracking_output_realtime
|
||||
|
||||
IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']
|
||||
VID_FORMAT = ['.mp4', '.avi']
|
||||
|
||||
def save_data(event, resultPath=None):
|
||||
'''事件轨迹子图保存'''
|
||||
if resultPath is None:
|
||||
resultPath = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
subimgpath = os.path.join(resultPath, f"{event.evtname}", "subimg")
|
||||
imgspath = os.path.join(resultPath, f"{event.evtname}", "imgs")
|
||||
if not os.path.exists(subimgpath):
|
||||
os.makedirs(subimgpath)
|
||||
if not os.path.exists(imgspath):
|
||||
os.makedirs(imgspath)
|
||||
##(2) 保存轨迹中的子图
|
||||
subimgpairs = event.save_event_subimg(subimgpath)
|
||||
for subimgName, subimg in subimgpairs:
|
||||
spath = os.path.join(subimgpath, subimgName)
|
||||
cv2.imwrite(spath, subimg)
|
||||
|
||||
##(3) 保存序列图像
|
||||
imgpairs = event.plot_save_image(imgspath)
|
||||
for imgname, img in imgpairs:
|
||||
spath = os.path.join(imgspath, imgname)
|
||||
cv2.imwrite(spath, img)
|
||||
##(4) 保存轨迹散点图
|
||||
img_cat = event.draw_tracks()
|
||||
trajpath = os.path.join(resultPath, "trajectory")
|
||||
if not os.path.exists(trajpath):
|
||||
os.makedirs(trajpath)
|
||||
traj_imgpath = os.path.join(trajpath, event.evtname+".png")
|
||||
cv2.imwrite(traj_imgpath, img_cat)
|
||||
|
||||
|
||||
def array2list(bboxes):
|
||||
'''
|
||||
将 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]
|
||||
'''
|
||||
lboxes = []
|
||||
if len(bboxes)==0:
|
||||
return []
|
||||
|
||||
trackID = np.unique(bboxes[:, 4].astype(int))
|
||||
track_ids = bboxes[:, 4].astype(int)
|
||||
for t_id in trackID:
|
||||
idx = np.where(track_ids == t_id)[0]
|
||||
box = bboxes[idx, :]
|
||||
lboxes.append(box)
|
||||
|
||||
return lboxes
|
||||
|
||||
|
||||
class ShoppingEvent:
|
||||
def __init__(self, eventpath, stype="data"):
|
||||
'''stype: str, 'source', 'data', 'realtime', 共三种 '''
|
||||
|
||||
self.eventpath = eventpath
|
||||
self.evtname = str(Path(eventpath).stem)
|
||||
self.barcode = ''
|
||||
self.evtType = ''
|
||||
|
||||
'''=========== path of image and video =========== '''
|
||||
self.back_videopath = ''
|
||||
self.front_videopath = ''
|
||||
self.back_imgpaths = []
|
||||
self.front_imgpaths = []
|
||||
|
||||
'''=========== process.data ==============================='''
|
||||
self.one2one = None
|
||||
self.one2n = None
|
||||
self.one2SN = None
|
||||
|
||||
'''=========== 0/1_track.data ============================='''
|
||||
self.back_yolobboxes = []
|
||||
self.back_yolofeats = []
|
||||
self.back_trackerboxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
self.back_trackerfeats = {}
|
||||
self.back_trackingboxes = []
|
||||
self.back_trackingfeats = []
|
||||
|
||||
self.front_yolobboxes = []
|
||||
self.front_yolofeats = []
|
||||
self.front_trackerboxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
self.front_trackerfeats = {}
|
||||
self.front_trackingboxes = []
|
||||
self.front_trackingfeats = []
|
||||
|
||||
'''=========== 0/1_tracking_output.data ==================='''
|
||||
self.back_boxes = []
|
||||
self.back_feats = []
|
||||
self.front_boxes = []
|
||||
self.front_feats = []
|
||||
|
||||
|
||||
if stype=="data":
|
||||
self.from_datafile(eventpath)
|
||||
if stype=="realtime":
|
||||
self.from_realtime_datafile(eventpath)
|
||||
if stype=="source":
|
||||
self.from_source_pkl(eventpath)
|
||||
|
||||
self.feats_select = np.empty((0, 256), dtype=np.float64)
|
||||
self.feats_compose = np.empty((0, 256), dtype=np.float64)
|
||||
self.select_feats()
|
||||
self.compose_feats()
|
||||
|
||||
# if stype=="image":
|
||||
# self.from_image(eventpath)
|
||||
|
||||
def kerndata(self, ShoppingDict, camtype="backCamera"):
|
||||
'''
|
||||
camtype: str, "backCamera" or "frontCamera"
|
||||
'''
|
||||
yoloboxes, resfeats = [], []
|
||||
trackerboxes = np.empty((0, 9), dtype=np.float64)
|
||||
trackefeats = {}
|
||||
trackingboxes, trackingfeats = [], []
|
||||
|
||||
frameDictList = ShoppingDict[camtype]["yoloResnetTracker"]
|
||||
for frameDict in frameDictList:
|
||||
yoloboxes.append(frameDict["bboxes"])
|
||||
|
||||
tboxes = frameDict["tboxes"]
|
||||
trackefeats.update(frameDict["feats"])
|
||||
|
||||
trackerboxes = np.concatenate((trackerboxes, np.array(tboxes)), axis=0)
|
||||
|
||||
Residual = ShoppingDict[camtype]["tracking"].Residual
|
||||
for track in Residual:
|
||||
trackingboxes.append(track.boxes)
|
||||
trackingfeats.append(track.features)
|
||||
kdata = (yoloboxes, resfeats, trackerboxes, trackefeats, trackingboxes, trackingfeats)
|
||||
|
||||
|
||||
tracking_out_boxes, tracking_out_feats = [], []
|
||||
Confirmed = ShoppingDict[camtype]["tracking"].Confirmed
|
||||
for track in Confirmed:
|
||||
tracking_out_boxes.append(track.boxes)
|
||||
tracking_out_feats.append(track.features)
|
||||
outdata = (tracking_out_boxes, tracking_out_feats)
|
||||
|
||||
return kdata, outdata
|
||||
|
||||
|
||||
def from_source_pkl(self, eventpath):
|
||||
with open(eventpath, 'rb') as f:
|
||||
ShoppingDict = pickle.load(f)
|
||||
|
||||
self.eventpath = ShoppingDict["eventPath"]
|
||||
self.evtname = ShoppingDict["eventName"]
|
||||
self.barcode = ShoppingDict["barcode"]
|
||||
|
||||
if len(ShoppingDict["one2n"]):
|
||||
self.one2n = ShoppingDict["one2n"]
|
||||
|
||||
'''=========== path of image and video =========== '''
|
||||
self.back_videopath = ShoppingDict["backCamera"]["videoPath"]
|
||||
self.front_videopath = ShoppingDict["frontCamera"]["videoPath"]
|
||||
self.back_imgpaths = ShoppingDict["backCamera"]["imagePaths"]
|
||||
self.front_imgpaths = ShoppingDict["frontCamera"]["imagePaths"]
|
||||
|
||||
|
||||
'''===========对应于 0/1_track.data ============================='''
|
||||
backdata, back_outdata = self.kerndata(ShoppingDict, "backCamera")
|
||||
frontdata, front_outdata = self.kerndata(ShoppingDict, "frontCamera")
|
||||
self.back_yolobboxes = backdata[0]
|
||||
self.back_yolofeats = backdata[1]
|
||||
self.back_trackerboxes = backdata[2]
|
||||
self.back_trackerfeats = [3]
|
||||
self.back_trackingboxes = [4]
|
||||
self.back_trackingfeats = [5]
|
||||
|
||||
self.front_yolobboxes = frontdata[0]
|
||||
self.front_yolofeats = frontdata[1]
|
||||
self.front_trackerboxes = frontdata[2]
|
||||
self.front_trackerfeats = frontdata[3]
|
||||
self.front_trackingboxes = frontdata[4]
|
||||
self.front_trackingfeats = frontdata[5]
|
||||
|
||||
'''===========对应于 0/1_tracking_output.data ============================='''
|
||||
self.back_boxes = back_outdata[0]
|
||||
self.back_feats = back_outdata[1]
|
||||
self.front_boxes = front_outdata[0]
|
||||
self.front_feats = front_outdata[1]
|
||||
|
||||
|
||||
def from_datafile(self, eventpath):
|
||||
evtList = self.evtname.split('_')
|
||||
if len(evtList)>=2 and len(evtList[-1])>=10 and evtList[-1].isdigit():
|
||||
self.barcode = evtList[-1]
|
||||
if len(evtList)==3 and evtList[-1]== evtList[-2]:
|
||||
self.evtType = 'input'
|
||||
else:
|
||||
self.evtType = 'other'
|
||||
|
||||
'''================ path of image ============='''
|
||||
frontImgs, frontFid = [], []
|
||||
backImgs, backFid = [], []
|
||||
for imgname in os.listdir(eventpath):
|
||||
name, ext = os.path.splitext(imgname)
|
||||
if ext not in IMG_FORMAT or name.find('frameId') < 0: continue
|
||||
if len(name.split('_')) != 3 and not name.split('_')[3].isdigit(): continue
|
||||
|
||||
CamerType = name.split('_')[0]
|
||||
frameId = int(name.split('_')[3])
|
||||
imgpath = os.path.join(eventpath, imgname)
|
||||
if CamerType == '0':
|
||||
backImgs.append(imgpath)
|
||||
backFid.append(frameId)
|
||||
if CamerType == '1':
|
||||
frontImgs.append(imgpath)
|
||||
frontFid.append(frameId)
|
||||
## 生成依据帧 ID 排序的前后摄图像地址列表
|
||||
frontIdx = np.argsort(np.array(frontFid))
|
||||
backIdx = np.argsort(np.array(backFid))
|
||||
self.front_imgpaths = [frontImgs[i] for i in frontIdx]
|
||||
self.back_imgpaths = [backImgs[i] for i in backIdx]
|
||||
|
||||
|
||||
'''================ path of video ============='''
|
||||
for vidname in os.listdir(eventpath):
|
||||
name, ext = os.path.splitext(vidname)
|
||||
if ext not in VID_FORMAT: continue
|
||||
vidpath = os.path.join(eventpath, vidname)
|
||||
|
||||
CamerType = name.split('_')[0]
|
||||
if CamerType == '0':
|
||||
self.back_videopath = vidpath
|
||||
if CamerType == '1':
|
||||
self.front_videopath = vidpath
|
||||
|
||||
'''================ process.data ============='''
|
||||
procpath = Path(eventpath).joinpath('process.data')
|
||||
if procpath.is_file():
|
||||
SimiDict = read_similar(procpath)
|
||||
self.one2one = SimiDict['one2one']
|
||||
self.one2n = SimiDict['one2n']
|
||||
self.one2SN = SimiDict['one2SN']
|
||||
|
||||
'''=========== 0/1_track.data & 0/1_tracking_output.data ======='''
|
||||
for dataname in os.listdir(eventpath):
|
||||
datapath = os.path.join(eventpath, dataname)
|
||||
if not os.path.isfile(datapath): continue
|
||||
CamerType = dataname.split('_')[0]
|
||||
|
||||
'''========== 0/1_track.data =========='''
|
||||
if dataname.find("_track.data")>0:
|
||||
bboxes, ffeats, trackerboxes, trackerfeats, trackingboxes, trackingfeats = extract_data(datapath)
|
||||
if CamerType == '0':
|
||||
self.back_yolobboxes = bboxes
|
||||
self.back_yolofeats = ffeats
|
||||
self.back_trackerboxes = trackerboxes
|
||||
self.back_trackerfeats = trackerfeats
|
||||
self.back_trackingboxes = trackingboxes
|
||||
self.back_trackingfeats = trackingfeats
|
||||
if CamerType == '1':
|
||||
self.front_yolobboxes = bboxes
|
||||
self.front_yolofeats = ffeats
|
||||
self.front_trackerboxes = trackerboxes
|
||||
self.front_trackerfeats = trackerfeats
|
||||
self.front_trackingboxes = trackingboxes
|
||||
self.front_trackingfeats = trackingfeats
|
||||
|
||||
'''========== 0/1_tracking_output.data =========='''
|
||||
if dataname.find("_tracking_output.data")>0:
|
||||
tracking_output_boxes, tracking_output_feats = read_tracking_output(datapath)
|
||||
if CamerType == '0':
|
||||
self.back_boxes = tracking_output_boxes
|
||||
self.back_feats = tracking_output_feats
|
||||
elif CamerType == '1':
|
||||
self.front_boxes = tracking_output_boxes
|
||||
self.front_feats = tracking_output_feats
|
||||
|
||||
def from_realtime_datafile(self, eventpath):
|
||||
# evtList = self.evtname.split('_')
|
||||
# if len(evtList)>=2 and len(evtList[-1])>=10 and evtList[-1].isdigit():
|
||||
# self.barcode = evtList[-1]
|
||||
# if len(evtList)==3 and evtList[-1]== evtList[-2]:
|
||||
# self.evtType = 'input'
|
||||
# else:
|
||||
# self.evtType = 'other'
|
||||
|
||||
'''================ path of video ============='''
|
||||
for vidname in os.listdir(eventpath):
|
||||
name, ext = os.path.splitext(vidname)
|
||||
if ext not in VID_FORMAT: continue
|
||||
vidpath = os.path.join(eventpath, vidname)
|
||||
|
||||
CamerType = name.split('_')[0]
|
||||
if CamerType == '0':
|
||||
self.back_videopath = vidpath
|
||||
if CamerType == '1':
|
||||
self.front_videopath = vidpath
|
||||
|
||||
'''================ process.data ============='''
|
||||
procpath = Path(eventpath).joinpath('process.data')
|
||||
if procpath.is_file():
|
||||
SimiDict = read_similar(procpath)
|
||||
self.one2one = SimiDict['one2one']
|
||||
self.one2n = SimiDict['one2n']
|
||||
self.one2SN = SimiDict['one2SN']
|
||||
|
||||
'''=========== 0/1_track.data & 0/1_tracking_output.data ======='''
|
||||
for dataname in os.listdir(eventpath):
|
||||
datapath = os.path.join(eventpath, dataname)
|
||||
if not os.path.isfile(datapath): continue
|
||||
CamerType = dataname.split('_')[0]
|
||||
'''========== 0/1_track.data =========='''
|
||||
if dataname.find("_track.data")>0:
|
||||
trackerboxes, trackerfeats = extract_data_realtime(datapath)
|
||||
if CamerType == '0':
|
||||
self.back_trackerboxes = trackerboxes
|
||||
self.back_trackerfeats = trackerfeats
|
||||
|
||||
if CamerType == '1':
|
||||
self.front_trackerboxes = trackerboxes
|
||||
self.front_trackerfeats = trackerfeats
|
||||
'''========== 0/1_tracking_output.data =========='''
|
||||
if dataname.find("_tracking_output.data")>0:
|
||||
trackingboxes, trackingfeats, tracking_outboxes, tracking_outfeats = read_tracking_output_realtime(datapath)
|
||||
if CamerType == '0':
|
||||
self.back_trackingboxes = trackingboxes
|
||||
self.back_trackingfeats = trackingfeats
|
||||
self.back_boxes = tracking_outboxes
|
||||
self.back_feats = tracking_outfeats
|
||||
elif CamerType == '1':
|
||||
self.front_trackingboxes = trackingboxes
|
||||
self.front_trackingfeats = trackingfeats
|
||||
self.front_boxes = tracking_outboxes
|
||||
self.front_feats = tracking_outfeats
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def compose_feats(self):
|
||||
'''事件的特征集成'''
|
||||
feats_compose = np.empty((0, 256), dtype=np.float64)
|
||||
if len(self.front_feats):
|
||||
for feat in self.front_feats:
|
||||
feats_compose = np.concatenate((feats_compose, feat), axis=0)
|
||||
if len(self.back_feats):
|
||||
for feat in self.back_feats:
|
||||
feats_compose = np.concatenate((feats_compose, feat), axis=0)
|
||||
self.feats_compose = feats_compose
|
||||
|
||||
def select_feats(self):
|
||||
'''事件的特征选择'''
|
||||
if len(self.front_feats):
|
||||
self.feats_select = self.front_feats[0]
|
||||
elif len(self.back_feats):
|
||||
self.feats_select = self.back_feats[0]
|
||||
|
||||
def plot_save_image(self, savepath):
|
||||
|
||||
def array2list(bboxes):
|
||||
'''[x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]'''
|
||||
frame_ids = bboxes[:, 7].astype(int)
|
||||
fID = np.unique(bboxes[:, 7].astype(int))
|
||||
fboxes = []
|
||||
for f_id in fID:
|
||||
idx = np.where(frame_ids==f_id)[0]
|
||||
box = bboxes[idx, :]
|
||||
fboxes.append((f_id, box))
|
||||
return fboxes
|
||||
|
||||
imgpairs = []
|
||||
cameras = ('front', 'back')
|
||||
for camera in cameras:
|
||||
if camera == 'front':
|
||||
boxes = self.front_trackerboxes
|
||||
imgpaths = self.front_imgpaths
|
||||
else:
|
||||
boxes = self.back_trackerboxes
|
||||
imgpaths = self.back_imgpaths
|
||||
|
||||
fboxes = array2list(boxes)
|
||||
for fid, fbox in fboxes:
|
||||
imgpath = imgpaths[int(fid-1)]
|
||||
|
||||
image = cv2.imread(imgpath)
|
||||
|
||||
annotator = Annotator(image.copy(), line_width=2)
|
||||
for i, box in enumerate(fbox):
|
||||
x1, y1, x2, y2, tid, score, cls, fid, bid = box
|
||||
label = f'{int(tid), int(cls)}'
|
||||
if tid >=0 and cls==0:
|
||||
color = colors(int(cls), True)
|
||||
elif tid >=0 and cls!=0:
|
||||
color = colors(int(tid), True)
|
||||
else:
|
||||
color = colors(19, True) # 19为调色板的最后一个元素
|
||||
xyxy = (x1/2, y1/2, x2/2, y2/2)
|
||||
annotator.box_label(xyxy, label, color=color)
|
||||
|
||||
im0 = annotator.result()
|
||||
|
||||
imgpairs.append((Path(imgpath).name, im0))
|
||||
|
||||
# spath = os.path.join(savepath, Path(imgpath).name)
|
||||
|
||||
|
||||
# cv2.imwrite(spath, im0)
|
||||
return imgpairs
|
||||
|
||||
|
||||
def save_event_subimg(self, savepath):
|
||||
'''
|
||||
功能: 保存一次购物事件的轨迹子图
|
||||
9 items: barcode, type, filepath, back_imgpaths, front_imgpaths,
|
||||
back_boxes, front_boxes, back_feats, front_feats,
|
||||
feats_compose, feats_select
|
||||
子图保存次序:先前摄、后后摄,以 k 为编号,和 "feats_compose" 中次序相同
|
||||
'''
|
||||
imgpairs = []
|
||||
cameras = ('front', 'back')
|
||||
for camera in cameras:
|
||||
boxes = np.empty((0, 9), dtype=np.float64) ##和类doTracks兼容
|
||||
if camera == 'front':
|
||||
for b in self.front_boxes:
|
||||
boxes = np.concatenate((boxes, b), axis=0)
|
||||
imgpaths = self.front_imgpaths
|
||||
else:
|
||||
for b in self.back_boxes:
|
||||
boxes = np.concatenate((boxes, b), axis=0)
|
||||
imgpaths = self.back_imgpaths
|
||||
|
||||
for i, box in enumerate(boxes):
|
||||
x1, y1, x2, y2, tid, score, cls, fid, bid = box
|
||||
|
||||
imgpath = imgpaths[int(fid-1)]
|
||||
image = cv2.imread(imgpath)
|
||||
|
||||
subimg = image[int(y1/2):int(y2/2), int(x1/2):int(x2/2), :]
|
||||
|
||||
camerType, timeTamp, _, frameID = os.path.basename(imgpath).split('.')[0].split('_')
|
||||
subimgName = f"cam{camerType}_{i}_tid{int(tid)}_fid({int(fid)}, {frameID}).png"
|
||||
|
||||
imgpairs.append((subimgName, subimg))
|
||||
|
||||
# spath = os.path.join(savepath, subimgName)
|
||||
|
||||
# cv2.imwrite(spath, subimg)
|
||||
return imgpairs
|
||||
# basename = os.path.basename(event['filepath'])
|
||||
print(f"Image saved: {os.path.basename(self.eventpath)}")
|
||||
|
||||
def draw_tracks(self):
|
||||
front_edge = cv2.imread(r"D:\DetectTracking\tracking\shopcart\cart_tempt\board_ftmp_line.png")
|
||||
back_edge = cv2.imread(r"D:\DetectTracking\tracking\shopcart\cart_tempt\edgeline.png")
|
||||
|
||||
front_trackerboxes = array2list(self.front_trackerboxes)
|
||||
back_trackerboxes = array2list(self.back_trackerboxes)
|
||||
|
||||
# img1, img2 = edgeline.copy(), edgeline.copy()
|
||||
img1 = drawTrack(front_trackerboxes, front_edge.copy())
|
||||
img2 = drawTrack(self.front_trackingboxes, front_edge.copy())
|
||||
|
||||
img3 = drawTrack(back_trackerboxes, back_edge.copy())
|
||||
img4 = drawTrack(self.back_trackingboxes, back_edge.copy())
|
||||
|
||||
|
||||
|
||||
imgcat1 = np.concatenate((img1, img2), axis = 1)
|
||||
H, W = imgcat1.shape[:2]
|
||||
cv2.line(imgcat1, (int(W/2), 0), (int(W/2), H), (128, 255, 128), 2)
|
||||
|
||||
imgcat2 = np.concatenate((img3, img4), axis = 1)
|
||||
H, W = imgcat2.shape[:2]
|
||||
cv2.line(imgcat2, (int(W/2), 0), (int(W/2), H), (128, 255, 128), 2)
|
||||
|
||||
|
||||
illus = [imgcat1, imgcat2]
|
||||
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)
|
||||
|
||||
return img_cat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
# pklpath = r"D:\DetectTracking\evtresult\images2\ShoppingDict.pkl"
|
||||
# evt = ShoppingEvent(pklpath, stype='source')
|
||||
|
||||
evtpath = r"\\192.168.1.28\share\测试视频数据以及日志\算法全流程测试\202412\images\20241209-160248-08edd5f6-1806-45ad-babf-7a4dd11cea60_6973226721445"
|
||||
evt = ShoppingEvent(evtpath, stype='data')
|
||||
|
||||
img_cat = evt.draw_tracks()
|
||||
|
||||
cv2.imwrite("a.png", img_cat)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
# main1()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
56
detecttracking/contrast/utils/tools.py
Normal file
56
detecttracking/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
|
182
detecttracking/contrast/utils/write_feature_json.py
Normal file
182
detecttracking/contrast/utils/write_feature_json.py
Normal file
@ -0,0 +1,182 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|
||||
@author: LiChen
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import pickle
|
||||
import numpy as np
|
||||
|
||||
import sys
|
||||
sys.path.append(r"D:\DetectTracking\contrast")
|
||||
|
||||
from config import config as conf
|
||||
# from img_data import library_imgs, temp_imgs, main_library_imgs, main_imgs_2
|
||||
# from test_logic import initModel,getFeatureList
|
||||
from model import resnet18
|
||||
import torch
|
||||
from PIL import Image
|
||||
|
||||
device = conf.device
|
||||
|
||||
def initModel():
|
||||
model = resnet18().to(device)
|
||||
model.load_state_dict(torch.load(conf.test_model, map_location=conf.device))
|
||||
model.eval()
|
||||
return model
|
||||
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def convert_rgba_to_rgb(image_path, output_path=None):
|
||||
"""
|
||||
将给定路径的4通道PNG图像转换为3通道,并保存到指定输出路径。
|
||||
|
||||
:param image_path: 输入图像的路径
|
||||
:param output_path: 转换后的图像保存路径
|
||||
"""
|
||||
# 打开图像
|
||||
img = Image.open(image_path)
|
||||
# 转换图像模式从RGBA到RGB
|
||||
# .convert('RGB')会丢弃Alpha通道并转换为纯RGB图像
|
||||
if img.mode == 'RGBA':
|
||||
# 转换为RGB模式
|
||||
img_rgb = img.convert('RGB')
|
||||
# 保存转换后的图像
|
||||
img_rgb.save(image_path)
|
||||
print(f"Image converted from RGBA to RGB and saved to {image_path}")
|
||||
# else:
|
||||
# # 如果已经是RGB或其他模式,直接保存
|
||||
# img.save(image_path)
|
||||
# print(f"Image already in {img.mode} mode, saved to {image_path}")
|
||||
|
||||
|
||||
def test_preprocess(images: list, actionModel=False) -> torch.Tensor:
|
||||
res = []
|
||||
for img in images:
|
||||
try:
|
||||
print(img)
|
||||
im = conf.test_transform(img) if actionModel else conf.test_transform(Image.open(img))
|
||||
res.append(im)
|
||||
except:
|
||||
continue
|
||||
data = torch.stack(res)
|
||||
return data
|
||||
|
||||
|
||||
def inference(images, model, actionModel=False):
|
||||
data = test_preprocess(images, actionModel)
|
||||
if torch.cuda.is_available():
|
||||
data = data.to(conf.device)
|
||||
features = model(data)
|
||||
return features
|
||||
|
||||
|
||||
def group_image(images, batch=64) -> list:
|
||||
"""Group image paths by batch size"""
|
||||
size = len(images)
|
||||
res = []
|
||||
for i in range(0, size, batch):
|
||||
end = min(batch + i, size)
|
||||
res.append(images[i:end])
|
||||
return res
|
||||
|
||||
def getFeatureList(barList, imgList, model):
|
||||
featList = [[] for i in range(len(barList))]
|
||||
for index, feat in enumerate(imgList):
|
||||
groups = group_image(feat)
|
||||
for group in groups:
|
||||
feat_tensor = inference(group, model)
|
||||
for fe in feat_tensor:
|
||||
if fe.device == 'cpu':
|
||||
fe_np = fe.squeeze().detach().numpy()
|
||||
else:
|
||||
fe_np = fe.squeeze().detach().cpu().numpy()
|
||||
featList[index].append(fe_np)
|
||||
return featList
|
||||
|
||||
def get_files(folder):
|
||||
file_dict = {}
|
||||
cnt = 0
|
||||
# barcode_list = ['6944649700065', '6924743915848', '6920459905012', '6901285991219', '6924882406269']
|
||||
for root, dirs, files in os.walk(folder):
|
||||
|
||||
folder_name = os.path.basename(root) # 获取当前文件夹名称
|
||||
print(folder_name)
|
||||
# with open('main_barcode.txt','a') as f:
|
||||
# f.write(folder_name + '\n')
|
||||
|
||||
# if len(dirs) == 0 and len(files) > 0 and folder_name in barcode_list: # 如果该文件夹没有子文件夹且有文件
|
||||
if len(dirs) == 0 and len(files) > 0: # 如果该文件夹没有子文件夹且有文件
|
||||
|
||||
file_names = [os.path.join(root, file) for file in files] # 获取所有文件名
|
||||
for file_name in file_names:
|
||||
try:
|
||||
convert_rgba_to_rgb(file_name)
|
||||
except:
|
||||
file_names.remove(file_name)
|
||||
cnt += len(file_names)
|
||||
file_dict[folder_name] = file_names
|
||||
print(cnt)
|
||||
|
||||
return file_dict
|
||||
|
||||
def normalize(queFeatList):
|
||||
for num1 in range(len(queFeatList)):
|
||||
for num2 in range(len(queFeatList[num1])):
|
||||
queFeatList[num1][num2] = queFeatList[num1][num2] / np.linalg.norm(queFeatList[num1][num2])
|
||||
return queFeatList
|
||||
def img2feature(imgs_dict, model, barcode_flag):
|
||||
if not len(imgs_dict) > 0:
|
||||
raise ValueError("No imgs files provided")
|
||||
queBarIdList = list(imgs_dict.keys())
|
||||
queImgsList = list(imgs_dict.values())
|
||||
queFeatList = getFeatureList(queBarIdList, queImgsList, model)
|
||||
queFeatList = normalize(queFeatList)
|
||||
return queBarIdList, queFeatList
|
||||
|
||||
|
||||
def createFeatureDict(imgs_dict, model,
|
||||
barcode_flag=False): ##imgs->{barcode1:[img1_1...img1_n], barcode2:[img2_1...img2_n]}
|
||||
dicts_all = {}
|
||||
value_list = []
|
||||
barcode_list, imgs_list = img2feature(imgs_dict, model, barcode_flag=False)
|
||||
for i in range(len(barcode_list)):
|
||||
dicts = {}
|
||||
|
||||
imgs_list_ = []
|
||||
for j in range(len(imgs_list[i])):
|
||||
imgs_list_.append(imgs_list[i][j].tolist())
|
||||
# with open('feature.txt','a') as f:
|
||||
# f.write(str(imgs_list[i][j].tolist())+'\n')
|
||||
|
||||
dicts['key'] = barcode_list[i]
|
||||
dicts['value'] = imgs_list_
|
||||
value_list.append(dicts)
|
||||
dicts_all['total'] = value_list
|
||||
print('dicts_all', dicts_all)
|
||||
with open('data_0909.json', 'a') as json_file:
|
||||
json.dump(dicts_all, json_file)
|
||||
|
||||
|
||||
def read_pkl_file(file_path):
|
||||
with open(file_path, 'rb') as file:
|
||||
data = pickle.load(file)
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
###将图片名称和模型推理特征向量字典存为json文件
|
||||
img_path = 'data/2000_train/base'
|
||||
imgs_dict = get_files(img_path)
|
||||
# print('imgs_dict', imgs_dict)
|
||||
model = initModel()
|
||||
createFeatureDict(imgs_dict, model, barcode_flag=False)
|
||||
###=======================================================
|
||||
# ## =========pkl转json================
|
||||
# contents = read_pkl_file('dicts_list_1887.pkl')
|
||||
# print(contents)
|
||||
# with open('data_1887.json', 'w') as json_file:
|
||||
# json.dump(contents, json_file)
|
Reference in New Issue
Block a user