# -*- coding: utf-8 -*- """ Created on Mon Mar 4 18:33:01 2024 @author: ym """ import numpy as np from sklearn.cluster import KMeans from .dotracks import MoveState, Track class frontTrack(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) self.hands = [] '''5个关键点(中心点、左上点、右上点、左下点、右下点 )轨迹特征''' # self.compute_cornpts_feats() self.CART_HIGH_THRESH1 = imgshape[1]/2.98 # if self.tid==10: # print(f"ID: {self.tid}") '''y1、y2静止状态区间,值是 boxes 中对 axis=0 的索引,不是帧索引''' det_y1 = np.diff(boxes[:, 1], axis=0) det_y2 = np.diff(boxes[:, 3], axis=0) self.static_y1, self.dynamic_y1 = self.compute_static_fids(det_y1) self.static_y2, self.dynamic_y2 = self.compute_static_fids(det_y2) self.isCornpoint = self.is_left_or_right_cornpoint() self.isBotmpoint = self.is_bottom_cornpoint() '''该函数依赖项: self.isCornpoint,不能在父类中初始化''' self.trajfeature() '''手部状态分析''' self.HAND_STATIC_THRESH = 100 self.CART_POSIT_0 = 430 self.CART_POSIT_1 = 620 def is_left_or_right_cornpoint(self): ''' 基于 all(boxes), boxes左下角点和图像左下角点重叠 或 boxes右下角点和图像左下角点重叠 ''' x1, y1 = self.boxes[:, 0], self.boxes[:, 1] x2, y2 = self.boxes[:, 2], self.boxes[:, 3] # Left-Bottom cornpoint condt1 = all(x1 < 5) and all(y2 > self.imgshape[1]-5) # Right-Bottom cornpoint condt2 = all(x2 > self.imgshape[0]-5) and all(y2 > self.imgshape[1]-5) condt = condt1 or condt2 return condt def is_edge_cornpoint(self): '''基于 all(boxes),boxes是否和图像左右边缘重叠''' x1, x2 = self.boxes[:, 0], self.boxes[:, 2] condt = all(x1 < 3) or all(x2 > self.imgshape[0]-3) return condt def is_bottom_cornpoint(self): '''基于 all(boxes),boxes是否和图像下边缘重叠''' condt = all(self.boxes[:, 3] > self.imgshape[1]-20) return condt # def is_OutTrack(self): # isout = False # if self.posState <= 1: # isout = True # return isout # ============================================================================= # def compute_static_fids(self, det_y, STATIC_THRESH = 8): # ''' # 前摄时,y一般选择为 box 的 y1 坐标,且需限定商品在购物车内。 # inputs: # y:1D array, # parameters: # STATIC_THRESH:轨迹处于静止状态的阈值。 # outputs: # 输出为差分值小于 STATIC_THRESH 的y中元素的(start, end)索引 # ranges = [(x1, y1), # (x1, y1), # ...] # ''' # # print(f"The ID is: {self.tid}") # # # det_y = np.diff(y, axis=0) # ranges, rangex = [], [] # # static_indices = np.where(np.abs(det_y) < STATIC_THRESH)[0] # # if len(static_indices) == 0: # rangex.append((0, len(det_y))) # return ranges, rangex # # start_index = static_indices[0] # # for i in range(1, len(static_indices)): # if static_indices[i] != static_indices[i-1] + 1: # ranges.append((start_index, static_indices[i-1] + 1)) # start_index = static_indices[i] # ranges.append((start_index, static_indices[-1] + 1)) # # if len(ranges) == 0: # rangex.append((0, len(det_y))) # return ranges, rangex # # idx1, idx2 = ranges[0][0], ranges[-1][1] # # if idx1 != 0: # rangex.append((0, idx1)) # # # 轨迹的最后阶段是运动状态 # for k in range(1, len(ranges)): # index1 = ranges[k-1][1] # index2 = ranges[k][0] # rangex.append((index1, index2)) # # if idx2 != len(det_y): # rangex.append((idx2, len(det_y))) # # return ranges, rangex # # ============================================================================= def is_static(self): assert self.frnum > 1, "boxes number must greater than 1" # print(f"The ID is: {self.tid}") # 手部和小孩目标不考虑 if self.cls == 0 or self.cls == 9: return False # boxes 全部 y2=1280 if self.isBotmpoint: return True boxes = self.boxes y0 = (boxes[:, 1]+boxes[:, 3])/2 ## 纵轴矢量和 sum_y0 = y0[-1] - y0[0] sum_y1 = boxes[-1, 1]-boxes[0, 1] sum_y2 = boxes[-1, 3]-boxes[0, 3] # 一些需要考虑的特殊情况 isbottom = max(boxes[:, 3]) > 1280-3 istop = min(boxes[:, 1]) < 3 isincart = min(y0) > self.CART_HIGH_THRESH1 uncert = abs(sum_y1)<100 and abs(sum_y2)<100 '''初始条件:商品中心点始终在购物车内、''' condt0 = max((boxes[:, 1]+boxes[:, 3])/2) > self.CART_HIGH_THRESH1 '''条件1:轨迹运动纵向和(y1 或 y2)描述商品轨迹长度,存在情况: (1). 检测框可能与图像上下边缘重合, (2). 上边或下边存在跳动 ''' if isbottom and istop: condt1 = abs(sum_y0) < 300 elif isbottom: # y2在底部,用y1表征运动 condt1 = sum_y1 > -120 and abs(sum_y0)<80 # 有底部点,方向向上阈值小于100 elif istop: # y1在顶部,用y2表征运动 condt1 = abs(sum_y2) < 100 else: condt1 = (abs(sum_y1) < 30 or abs(sum_y2)<30) '''条件2:轨迹的开始和结束阶段均处于静止状态, 利用静止状态区间判断,用 y1 a. 商品在购物车内, b. 检测框的起始阶段和结束阶段均为静止状态 c. 静止帧长度 > 3''' condt2 = False if len(self.static_y1)>=2: condt_s0 = self.static_y1[0][0]==0 and self.static_y1[0][1] - self.static_y1[0][0] >= 3 condt_s1 = self.static_y1[-1][1]==self.frnum-1 and self.static_y1[-1][1] - self.static_y1[-1][0] >= 3 condt2 = condt_s0 and condt_s1 and isincart condt = condt0 and (condt1 or condt2) return condt def is_upward(self): '''判断商品是否取出,''' print(f"The ID is: {self.tid}") def is_free_move(self): if self.frnum == 1: return True # print(f"The ID is: {self.tid}") y0 = (self.boxes[:, 1] + self.boxes[:, 3]) / 2 det_y0 = np.diff(y0, axis=0) sum_y0 = y0[-1] - y0[0] '''情况1:中心点向下 ''' ## 初始条件:商品第一次检测到在购物车内 condt0 = y0[0] > self.CART_HIGH_THRESH1 condt_a = False ## 条件1:商品初始为静止状态,静止条件应严格一些 condt11, condt12 = False, False if len(self.static_y1)>0: condt11 = self.static_y1[0][0]==0 and self.static_y1[0][1] - self.static_y1[0][0] >= 5 if len(self.static_y2)>0: condt12 = self.static_y2[0][0]==0 and self.static_y2[0][1] - self.static_y2[0][0] >= 5 # 条件2:商品中心发生向下移动 condt2 = y0[-1] > y0[0] # 综合判断a condt_a = condt0 and (condt11 or condt12) and condt2 '''情况2:中心点向上 ''' ## 商品中心点向上移动,但没有关联的Hand轨迹,也不是左右边界点 condt_b = condt0 and len(self.hands)==0 and y0[-1] < y0[0] and (not self.is_edge_cornpoint()) '''情况3: 商品在购物车内,但运动方向无序''' ## 中心点在购物车内,纵向轨迹和小于轨迹差中绝对值最大的两个值的和,说明运动没有主方向 condt_c = False if self.frnum > 3: condt_c = all(y0>self.CART_HIGH_THRESH1) and \ (abs(sum_y0) < sum(np.sort(np.abs(det_y0))[::-1][:2])-1) condt = (condt_a or condt_b or condt_c) and self.cls!=0 return condt