update
This commit is contained in:
304
ytracking/tracking/dotrack/track_back.py
Normal file
304
ytracking/tracking/dotrack/track_back.py
Normal file
@ -0,0 +1,304 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Mon Mar 4 18:28:47 2024
|
||||
|
||||
@author: ym
|
||||
"""
|
||||
import cv2
|
||||
import numpy as np
|
||||
from scipy.spatial.distance import cdist
|
||||
from sklearn.decomposition import PCA
|
||||
from .dotracks import MoveState, Track
|
||||
from tools.config import cfg
|
||||
|
||||
class backTrack(Track):
|
||||
# boxes: [x1, y1, x2, y2, track_id, score, cls, frame_index, box_index]
|
||||
# 0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
def __init__(self, boxes, imgshape=(1024, 1280)):
|
||||
|
||||
super().__init__(boxes, imgshape)
|
||||
|
||||
'''(cent_x, cent_y, mean_w, mean_h)'''
|
||||
|
||||
|
||||
|
||||
|
||||
'''5个关键点(中心点、左上点、右上点、左下点、右下点 )轨迹特征'''
|
||||
self.compute_cornpts_feats()
|
||||
|
||||
'''该函数依赖项: self.cornpoints'''
|
||||
self.isCornpoint = self.isimgborder()
|
||||
|
||||
'''该函数依赖项: self.cornpoints、self.isCornpoint,定义 10 个轨迹特征:
|
||||
self.trajectory, self.trajmin, self.trajlens, self.trajdist
|
||||
self.feature = [trajlen_min, trajlen_max,
|
||||
trajdist_min, trajdist_max,
|
||||
trajlen_rate, trajdist_rate] '''
|
||||
self.trajfeature()
|
||||
|
||||
|
||||
|
||||
|
||||
'''静止点帧索引'''
|
||||
self.static_index = self.compute_static_fids()
|
||||
|
||||
'''运动点帧索引(运动帧两端的静止帧索引)'''
|
||||
self.moving_index = self.compute_moving_fids()
|
||||
|
||||
'''该函数依赖项: self.cornpoints,定义 4 个商品位置变量:
|
||||
self.Cent_isIncart, self.LB_isIncart, self.RB_isIncart
|
||||
self.posState = self.Cent_isIncart+self.LB_isIncart+self.RB_isIncart'''
|
||||
self.PositionState()
|
||||
|
||||
'''self.feature_ious = (incart_iou, outcart_iou, cartboarder_iou, maxbox_iou, minbox_iou)
|
||||
self.incartrates = incartrates'''
|
||||
self.compute_ious_feat()
|
||||
|
||||
# self.PCA()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# def compute_cornpoints(self):
|
||||
# '''
|
||||
# cornpoints 共10项,分别是个点的坐标值(x, y)
|
||||
# (center, top_left, top_right, bottom_left, bottom_right)
|
||||
# '''
|
||||
# boxes = self.boxes
|
||||
# cornpoints = np.zeros((self.frnum, 10))
|
||||
# cornpoints[:,0], cornpoints[:,1] = boxes[:, 0], boxes[:, 1]
|
||||
# cornpoints[:,2], cornpoints[:,3] = boxes[:, 0] - boxes[:, 2]/2, boxes[:, 1] - boxes[:, 3]/2
|
||||
# cornpoints[:,4], cornpoints[:,5] = boxes[:, 0] + boxes[:, 2]/2, boxes[:, 1] - boxes[:, 3]/2
|
||||
# cornpoints[:,6], cornpoints[:,7] = boxes[:, 0] - boxes[:, 2]/2, boxes[:, 1] + boxes[:, 3]/2
|
||||
# cornpoints[:,8], cornpoints[:,9] = boxes[:, 0] + boxes[:, 2]/2, boxes[:, 1] + boxes[:, 3]/2
|
||||
#
|
||||
# self.cornpoints = cornpoints
|
||||
# =============================================================================
|
||||
|
||||
def isimgborder(self, BoundPixel=10, BoundThresh=0.3):
|
||||
|
||||
x1, y1 = self.cornpoints[:,2], self.cornpoints[:,3],
|
||||
x2, y2 = self.cornpoints[:,8], self.cornpoints[:,9]
|
||||
|
||||
cont1 = sum(abs(x1)<BoundPixel) / self.frnum > BoundThresh
|
||||
cont2 = sum(abs(y1)<BoundPixel) / self.frnum > BoundThresh
|
||||
cont3 = sum(abs(x2-self.imgshape[0])<BoundPixel) / self.frnum > BoundThresh
|
||||
cont4 = sum(abs(y2-self.imgshape[1])<BoundPixel) / self.frnum > BoundThresh
|
||||
|
||||
cont = cont1 or cont2 or cont3 or cont4
|
||||
isCornpoint = False
|
||||
if cont:
|
||||
isCornpoint = True
|
||||
|
||||
return isCornpoint
|
||||
|
||||
|
||||
def PositionState(self, camerType="back"):
|
||||
'''
|
||||
camerType: back, 后置摄像头
|
||||
front, 前置摄像头
|
||||
'''
|
||||
if camerType=="front":
|
||||
incart = cv2.imread(cfg.incart, cv2.IMREAD_GRAYSCALE)
|
||||
else:
|
||||
incart = cv2.imread(cfg.incart_ftmp, cv2.IMREAD_GRAYSCALE)
|
||||
|
||||
xc, yc = self.cornpoints[:,0].clip(0,self.imgshape[0]-1).astype(np.int64), self.cornpoints[:,1].clip(0,self.imgshape[1]-1).astype(np.int64)
|
||||
x1, y1 = self.cornpoints[:,6].clip(0,self.imgshape[0]-1).astype(np.int64), self.cornpoints[:,7].clip(0,self.imgshape[1]-1).astype(np.int64)
|
||||
x2, y2 = self.cornpoints[:,8].clip(0,self.imgshape[0]-1).astype(np.int64), self.cornpoints[:,9].clip(0,self.imgshape[1]-1).astype(np.int64)
|
||||
|
||||
# print(self.tid)
|
||||
Cent_inCartnum = np.count_nonzero(incart[(yc, xc)])
|
||||
LB_inCartnum = np.count_nonzero(incart[(y1, x1)])
|
||||
RB_inCartnum = np.count_nonzero(incart[(y2, x2)])
|
||||
|
||||
self.Cent_isIncart = False
|
||||
self.LB_isIncart = False
|
||||
self.RB_isIncart = False
|
||||
if Cent_inCartnum: self.Cent_isIncart = True
|
||||
if LB_inCartnum: self.LB_isIncart = True
|
||||
if RB_inCartnum: self.RB_isIncart = True
|
||||
|
||||
self.posState = self.Cent_isIncart+self.LB_isIncart+self.RB_isIncart
|
||||
|
||||
|
||||
|
||||
def PCA(self):
|
||||
self.pca = PCA()
|
||||
|
||||
X = self.cornpoints[:, 0:2]
|
||||
self.pca.fit(X)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def compute_ious_feat(self):
|
||||
'''输出:
|
||||
self.feature_ious = (incart_iou, outcart_iou, cartboarder_iou, maxbox_iou, minbox_iou)
|
||||
self.incartrates = incartrates,
|
||||
其中:
|
||||
boxes流:track中所有boxes形成的轨迹图,可分为三部分:incart, outcart, cartboarder
|
||||
incart_iou, outcart_iou, cartboarder_iou:各部分和 boxes流的 iou。
|
||||
incart_iou = 0,track在购物车外,
|
||||
outcart_iou = 0,track在购物车内,也可能是通过左下角、右下角置入购物车,
|
||||
maxbox_iou, minbox_iou:track中最大、最小 box 和boxes流的iou,二者差值越小,越接近 1,表明track的运动型越小。
|
||||
incartrates: 各box和incart的iou时序,由小变大,反应的是置入过程,由大变小,反应的是取出过程
|
||||
'''
|
||||
incart = cv2.imread(cfg.incart, cv2.IMREAD_GRAYSCALE)
|
||||
outcart = cv2.imread(cfg.outcart, cv2.IMREAD_GRAYSCALE)
|
||||
cartboarder = cv2.imread(cfg.cartboarder, cv2.IMREAD_GRAYSCALE)
|
||||
|
||||
incartrates = []
|
||||
temp = np.zeros(incart.shape, np.uint8)
|
||||
maxarea, minarea = 0, self.imgshape[0]*self.imgshape[1]
|
||||
for i in range(self.frnum):
|
||||
# x, y, w, h = self.boxes[i, 0:4]
|
||||
|
||||
x = (self.boxes[i, 2] + self.boxes[i, 0]) / 2
|
||||
w = (self.boxes[i, 2] - self.boxes[i, 0]) / 2
|
||||
y = (self.boxes[i, 3] + self.boxes[i, 1]) / 2
|
||||
h = (self.boxes[i, 3] - self.boxes[i, 1]) / 2
|
||||
|
||||
|
||||
if w*h > maxarea: maxarea = w*h
|
||||
if w*h < minarea: minarea = w*h
|
||||
cv2.rectangle(temp, (int(x-w/2), int(y-h/2)), (int(x+w/2), int(y+h/2)), 255, cv2.FILLED)
|
||||
|
||||
temp1 = np.zeros(incart.shape, np.uint8)
|
||||
cv2.rectangle(temp1, (int(x-w/2), int(y-h/2)), (int(x+w/2), int(y+h/2)), 255, cv2.FILLED)
|
||||
temp2 = cv2.bitwise_and(incart, temp1)
|
||||
inrate = cv2.countNonZero(temp1)/(w*h)
|
||||
incartrates.append(inrate)
|
||||
|
||||
isincart = cv2.bitwise_and(incart, temp)
|
||||
isoutcart = cv2.bitwise_and(outcart, temp)
|
||||
iscartboarder = cv2.bitwise_and(cartboarder, temp)
|
||||
|
||||
num_temp = cv2.countNonZero(temp)
|
||||
num_incart = cv2.countNonZero(isincart)
|
||||
num_outcart = cv2.countNonZero(isoutcart)
|
||||
num_cartboarder = cv2.countNonZero(iscartboarder)
|
||||
|
||||
incart_iou = num_incart/num_temp
|
||||
outcart_iou = num_outcart/num_temp
|
||||
cartboarder_iou = num_cartboarder/num_temp
|
||||
maxbox_iou = maxarea/num_temp
|
||||
minbox_iou = minarea/num_temp
|
||||
|
||||
self.feature_ious = (incart_iou, outcart_iou, cartboarder_iou, maxbox_iou, minbox_iou)
|
||||
self.incartrates = incartrates
|
||||
|
||||
|
||||
|
||||
|
||||
def compute_static_fids(self, thresh1 = 12, thresh2 = 3):
|
||||
'''
|
||||
计算 track 的轨迹中相对处于静止状态的轨迹点的(start_frame_id, end_frame_id)
|
||||
thresh1: 相邻两帧目标中心点是否静止的的阈值,以像素为单位,
|
||||
thresh2: 连续捕捉到目标处于静止状态的帧数
|
||||
'''
|
||||
|
||||
BoundPixel = 8
|
||||
x1, y1 = self.cornpoints[:,2], self.cornpoints[:,3],
|
||||
x2, y2 = self.cornpoints[:,8], self.cornpoints[:,9]
|
||||
cont1 = sum(abs(x1)<BoundPixel) > 3
|
||||
# cont2 = sum(abs(y1)<BoundPixel) > 3
|
||||
cont3 = sum(abs(x2-self.imgshape[0])<BoundPixel) > 3
|
||||
# cont4 = sum(abs(y2-self.imgshape[1])<BoundPixel) > 3
|
||||
cont = not(cont1 or cont3)
|
||||
|
||||
## ============== 下一步,启用中心点,选择具有最小运动幅度的角点作为参考点
|
||||
|
||||
static_index = []
|
||||
if self.frnum>=2 and cont:
|
||||
x1 = self.boxes[1:,7]
|
||||
x2 = [i for i in range(int(min(x1)), int(max(x1)+1))]
|
||||
dist_adjc = np.interp(x2, x1, self.trajmin)
|
||||
|
||||
|
||||
# dist_adjc = self.trajmin
|
||||
|
||||
static_thresh = (dist_adjc < thresh1)[:, None].astype(np.uint8)
|
||||
static_cnts, _ = cv2.findContours(static_thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
|
||||
|
||||
for cnt in static_cnts:
|
||||
_, start, _, num = cv2.boundingRect(cnt)
|
||||
end = start + num
|
||||
if num <= thresh2:
|
||||
continue
|
||||
static_index.append((start, end))
|
||||
|
||||
# =============================================================================
|
||||
# '''========= 输出帧id,不太合适 ========='''
|
||||
# static_fids = []
|
||||
# for i in range(len(static_index)):
|
||||
# i1, i2 = static_index[i]
|
||||
# fid1, fid2 = boxes[i1, 7], boxes[i2, 7]
|
||||
# static_fids.append([fid1, fid2])
|
||||
# static_fids = np.array(static_fids)
|
||||
# =============================================================================
|
||||
|
||||
static_index = np.array(static_index)
|
||||
if static_index.size:
|
||||
indx = np.argsort(static_index[:, 0])
|
||||
static_index = static_index[indx]
|
||||
|
||||
return static_index
|
||||
|
||||
def compute_moving_fids(self, thresh1 = 12, thresh2 = 3):
|
||||
'''
|
||||
计算 track 的轨迹中运动轨迹点的(start_frame_id, end_frame_id)
|
||||
thresh1: 相邻两帧目标中心点是否运动的阈值,以像素为单位,
|
||||
thresh2: 连续捕捉到目标连续运动的帧数
|
||||
目标:
|
||||
1. 计算轨迹方向
|
||||
2. 计算和手部运动的关联性
|
||||
'''
|
||||
moving_index = []
|
||||
if self.frnum>=2:
|
||||
x1 = self.boxes[1:,7]
|
||||
x2 = [i for i in range(int(min(x1)), int(max(x1)+1))]
|
||||
dist_adjc = np.interp(x2, x1, self.trajmin)
|
||||
|
||||
moving_thresh = (dist_adjc >= thresh1)[:, None].astype(np.uint8)
|
||||
moving_cnts, _ = cv2.findContours(moving_thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
|
||||
|
||||
for cnt in moving_cnts:
|
||||
_, start, _, num = cv2.boundingRect(cnt)
|
||||
if num < thresh2:
|
||||
continue
|
||||
end = start + num
|
||||
moving_index.append((start, end))
|
||||
|
||||
# =============================================================================
|
||||
# '''========= 输出帧id,不太合适 ========='''
|
||||
# moving_fids = []
|
||||
# for i in range(len(moving_index)):
|
||||
# i1, i2 = moving_index[i]
|
||||
# fid1, fid2 = boxes[i1, 7], boxes[i2, 7]
|
||||
# moving_fids.append([fid1, fid2])
|
||||
# moving_fids = np.array(moving_fids)
|
||||
# =============================================================================
|
||||
moving_index = np.array(moving_index)
|
||||
if moving_index.size:
|
||||
indx = np.argsort(moving_index[:, 0])
|
||||
moving_index = moving_index[indx]
|
||||
|
||||
return moving_index
|
||||
|
||||
|
||||
|
||||
|
||||
def compute_distance(self):
|
||||
pass
|
||||
|
||||
|
||||
def move_start_fid(self):
|
||||
pass
|
||||
|
||||
|
||||
def move_end_fid(self):
|
||||
pass
|
Reference in New Issue
Block a user