241 lines
9.0 KiB
Python
241 lines
9.0 KiB
Python
# -*- 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 pathlib import Path
|
||
curpath = Path(__file__).resolve().parents[0]
|
||
curpath = Path(curpath)
|
||
parpath = curpath.parent
|
||
|
||
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, features, imgshape=(1024, 1280)):
|
||
|
||
super().__init__(boxes, features, imgshape)
|
||
|
||
'''该函数依赖项: self.cornpoints
|
||
MarginState: list, seven elements, 表示轨迹中boxes出现在图像的
|
||
[左上,右上,左中,右中,左下,右下底部]
|
||
'''
|
||
self.isCornpoint, self.MarginState = self.isimgborder()
|
||
|
||
'''该函数依赖项: self.isCornpoint,不能在父类中初始化'''
|
||
self.trajfeature()
|
||
|
||
|
||
'''静止点帧索引'''
|
||
# self.static_index = self.compute_static_fids()
|
||
|
||
'''运动点帧索引(运动帧两端的静止帧索引)'''
|
||
# self.moving_index = self.compute_dynamic_fids()
|
||
|
||
self.static_index, self.moving_index = self.compute_static_dynamic_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(camerType="back")
|
||
|
||
'''self.feature_ious = (incart_iou, outcart_iou, cartboarder_iou, maxbox_iou, minbox_iou)
|
||
self.incartrates = incartrates'''
|
||
self.compute_ious_feat()
|
||
|
||
|
||
|
||
|
||
def isimgborder(self, BoundPixel=10, BoundThresh=0.3):
|
||
|
||
x1, y1 = self.cornpoints[:,2], self.cornpoints[:,3],
|
||
x2, y2 = self.cornpoints[:,8], self.cornpoints[:,9]
|
||
|
||
condt1 = sum(abs(x1)<BoundPixel) / self.frnum > BoundThresh
|
||
condt2 = sum(abs(y1)<BoundPixel) / self.frnum > BoundThresh
|
||
condt3 = sum(abs(x2-self.imgshape[0])<BoundPixel) / self.frnum > BoundThresh
|
||
condt4 = sum(abs(y2-self.imgshape[1])<BoundPixel) / self.frnum > BoundThresh
|
||
|
||
condt = condt1 or condt2 or condt3 or condt4
|
||
isCornpoint = False
|
||
if condt:
|
||
isCornpoint = True
|
||
|
||
condtA = condt1 and condt2
|
||
condtB = condt3 and condt2
|
||
condtC = condt1 and not condt2 and not condt4
|
||
condtD = condt3 and not condt2 and not condt4
|
||
condtE = condt1 and condt4
|
||
condtF = condt3 and condt4
|
||
condtG = condt4 and not condt1 and not condt3
|
||
MarginState = [condtA, condtB, condtC, condtD, condtE, condtF, condtG]
|
||
|
||
return isCornpoint, MarginState
|
||
|
||
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(str(parpath/"shopcart/cart_tempt/incart.png"), cv2.IMREAD_GRAYSCALE)
|
||
outcart = cv2.imread(str(parpath/"shopcart/cart_tempt/outcart.png"), cv2.IMREAD_GRAYSCALE)
|
||
cartboarder = cv2.imread(str(parpath/"shopcart/cart_tempt/cartboarder.png"), 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_dynamic_fids(self):
|
||
|
||
if self.MarginState[0] or self.MarginState[2]:
|
||
idx1 = 4
|
||
elif self.MarginState[1] or self.MarginState[3]:
|
||
idx1 = 3
|
||
elif self.MarginState[4]:
|
||
idx1 = 2
|
||
elif self.MarginState[5]:
|
||
idx1 = 1
|
||
elif self.MarginState[6]:
|
||
if self.trajlens[1] < self.trajlens[2]:
|
||
idx1 = 1
|
||
else:
|
||
idx1 = 2
|
||
else:
|
||
idx1 = self.trajlens.index(min(self.trajlens))
|
||
|
||
# idx1 = self.trajlens.index(min(self.trajlens))
|
||
trajmin = self.trajectory[idx1]
|
||
|
||
static, dynamic = self.pt_state_fids(trajmin)
|
||
|
||
static = np.array(static)
|
||
dynamic = np.array(dynamic)
|
||
|
||
if static.size:
|
||
indx = np.argsort(static[:, 0])
|
||
static = static[indx]
|
||
if dynamic.size:
|
||
indx = np.argsort(dynamic[:, 0])
|
||
dynamic = dynamic[indx]
|
||
|
||
return static, dynamic
|
||
|
||
|
||
def is_static(self):
|
||
'''静态情况 1: 目标关键点最小相对运动轨迹 < 0.2, 指标值偏大
|
||
TrajFeat = [trajlen_min, trajlen_max,
|
||
trajdist_min, trajdist_max,
|
||
trajlen_rate, trajdist_rate]
|
||
'''
|
||
# print(f"TrackID: {self.tid}")
|
||
|
||
boxes = self.boxes
|
||
|
||
'''静态情况 1: '''
|
||
condt1 = self.TrajFeat[5] < 0.2 or self.TrajFeat[3] < 120
|
||
|
||
'''静态情况 2: 目标初始状态为静止,适当放宽关键点最小相对运动轨迹 < 0.5'''
|
||
condt2 = self.static_index.size > 0 \
|
||
and self.static_index[0, 0] <= 2 \
|
||
and self.static_index[0, 1] >= 5 \
|
||
and self.TrajFeat[5] < 0.5 \
|
||
and self.TrajFeat[1] < 240 \
|
||
and self.isWholeInCart
|
||
# and self.posState >= 2
|
||
# and self.TrajFeat[0] < 240 \
|
||
|
||
'''静态情况 3: 目标初始状态和最终状态均为静止'''
|
||
condt3 = self.static_index.shape[0] >= 2 \
|
||
and self.static_index[0, 0] <= 2 \
|
||
and self.static_index[0, 1] >= 5 \
|
||
and self.static_index[-1, 1] >= self.frnum-3 \
|
||
and self.TrajFeat[1] < 240 \
|
||
and self.isWholeInCart
|
||
# and self.posState >= 2
|
||
# and self.TrajFeat[0] < 240 \
|
||
|
||
condt4 = self.static_index.shape[0] >= 2 \
|
||
and self.static_index[0, 0] <= 2 \
|
||
and self.static_index[0, 1] >= 6 \
|
||
and self.static_index[-1, 0] <= self.frnum-5 \
|
||
and self.static_index[-1, 1] >= self.frnum-2
|
||
|
||
condt = condt1 or condt2 or condt3 or condt4
|
||
|
||
return condt
|
||
|
||
|
||
|
||
|
||
def is_OutTrack(self):
|
||
if self.posState <= 1:
|
||
isout = True
|
||
else:
|
||
isout = False
|
||
return isout
|
||
|
||
def compute_distance(self):
|
||
pass
|
||
|
||
def move_start_fid(self):
|
||
pass
|
||
|
||
def move_end_fid(self):
|
||
pass |