You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

133 lines
4.1 KiB

from dataclasses import dataclass, field
from numbers import Number
from typing import Optional, Dict, Deque
from collections import deque
import numpy as np
from dataclasses_json import dataclass_json, config
import utils
@dataclass_json
@dataclass
class Point:
x:float
y:float
def __iter__(self): # 使对象可迭代,可直接转为元组
yield self.x
yield self.y
@dataclass
class RectangleArea:
x: int
y: int
w: int
h: int
@classmethod
def from_dict(cls, data: dict):
return cls(
x=data['x'],
y=data['y'],
w=data['w'],
h = data['h'])
@dataclass
class Threshold:
binary: int
gauss: int
@dataclass_json
@dataclass
class TargetInfo:
# 标靶方形区域
rectangle_area:RectangleArea
threshold:Threshold
# 标靶物理半径
radius:float=0.0
id:int =-1
desc:str=""
base:bool=False
def __init__(self,id,desc,rectangle_area:RectangleArea,radius,threshold:Threshold,base:bool,**kwargs):
self.id = id
self.desc = desc
self.rectangle_area=rectangle_area
self.radius=radius
self.threshold=threshold
self.base=base
@classmethod
def from_dict(cls,data: dict):
return cls(data['id'],data['rectangle_area'],data['radius'])
@dataclass_json
@dataclass
class HandlerInfo:
# 初始话
is_init=True
radius_pix:float= 1.0
pix_length:float=0.0
# 标靶中心
center_point_queue:Deque[Point] = field(default_factory=lambda: deque(maxlen=10))
center_point: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
center_init : Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
# 标靶位移(像素)
displacement_pix: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
displacement_phy: Optional[Point]= field(default=None, metadata=config(exclude=lambda x: x is None))
def calculate_mean(self)-> Point:
"""计算队列中所有数据的均值"""
if self.center_point_queue:
length=len(self.center_point_queue)
mean_x = sum(p.x for p in self.center_point_queue) / length
mean_y = sum(p.y for p in self.center_point_queue) / length
return Point(mean_x, mean_y)
else:
return None
def enqueue_center_point(self, data) -> Point:
"""入队操作"""
self.center_point_queue.append(data)
return self.calculate_mean()
@dataclass_json
@dataclass
class CircleTarget:
# 标靶方形区域
info:TargetInfo
# 标靶透视矩阵
perspective: np.ndarray = field(
metadata=config(
encoder=utils.encode_perspective,
decoder=utils.decode_perspective
)
)
handler_info: Optional[HandlerInfo]=None
# def __init__(self,info:TargetInfo,center_point,center_init,displacement_pix,displacement_phy):
# self.info=info
# self.center_point=center_point
# self.center_init=center_init
# self. displacement_pix=displacement_pix
# self.displacement_phy=displacement_phy
@classmethod
def init_by_info(cls,t:TargetInfo):
return CircleTarget(t,None,None,None,None)
def circle_displacement_pix(self):
previous = self.handler_info.center_init
if previous != ():
self.handler_info.displacement_pix = Point(self.handler_info.center_point.x - previous.x,
self.handler_info.center_point.y - previous.y)
return self
def circle_displacement_phy(self):
if self.info.radius != 0 and self.handler_info.displacement_pix is not None:
# 单位像素->距离
self.handler_info.pix_length = self.info.radius / self.handler_info.radius_pix
offset_x = round(float(self.handler_info.displacement_pix.x * self.handler_info.pix_length), 5)
offset_y = round(float(self.handler_info.displacement_pix.y * self.handler_info.pix_length), 5)
self.handler_info.displacement_phy = Point(offset_x, offset_y)
return self