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.

395 lines
16 KiB

# NeoTracker SDK
## 1. 范围
目前对标准跟踪器的解耦方案如下:
![images](doc/images/image.png)
本文档描述的NeoTracker SDK为上图蓝色部分包含对空对地搜索、传统跟踪算法逻辑并与NPU设备运行的AI识别与AI跟踪算法进行交互。
## 2.图像
接口中图像使用平台定义的GD_VIDEO_FRAME_S。
```C++
#ifndef GD_VIDEO_FRAME_S
#define GD_VIDEO_FRAME_S
typedef enum _gd_pixel_format_e {
GD_PIXEL_FORMAT_NONE = 0,
GD_PIXEL_FORMAT_YUV420P,
GD_PIXEL_FORMAT_YUV422P,
GD_PIXEL_FORMAT_NV12,
GD_PIXEL_FORMAT_NV21,
GD_PIXEL_FORMAT_NV16,
GD_PIXEL_FORMAT_NV61,
GD_PIXEL_FORMAT_RGB_PLANAR,
GD_PIXEL_FORMAT_BGR_PLANAR,
GD_PIXEL_FORMAT_RGB_PACKED,
GD_PIXEL_FORMAT_BGR_PACKED,
GD_PIXEL_FORMAT_GRAY_Y8,
GD_PIXEL_FORMAT_GRAY_Y16,
GD_PIXEL_FORMAT_GRAY_Y16Y8,
GD_PIXEL_FORMAT_BUTT
} GD_PIXEL_FORMAT_E;
typedef struct _gd_video_frame_s {
unsigned int u32Width;
unsigned int u32Height;
GD_PIXEL_FORMAT_E enPixelFormat;
unsigned int u32Stride[3];
unsigned long long u64PhyAddr[3];
unsigned char* u64VirAddr[3];
unsigned int u32TimeRef;
unsigned int u32FrameCnt;
} GD_VIDEO_FRAME_S;
#endif
```
图像数据结构引用平台室《图像格式要求》,该格式相对于传统算法输入图像格式,特点是内存可以不连续
1yuv、RGB不同通道的地址可以不连续
2数据带有stride属性目前海思平台上广泛使用这种数据类型用于字节对齐加快处理速度。
目前对数据结构的支持如下:
| 模块 | Y16 | Y8 | NV12 | RGB_PACKED | 其他 |
| ---- | ---- | ---- | ---- | ---------- | ---- |
| DST | 支持 | x | x | x | x |
| DAT | 支持 | 支持 | x | x | x |
| KCF | 支持 | 支持 | 支持 | 支持 | x |
| TLD | 支持 | 支持 | 支持 | 支持 | x |
| OCC | 支持 | 支持 | 支持 | 支持 | x |
><font color=Red>**目前算法内部对数据的处理基于连续内存因此暂不支持stride特性。如图像通道不满足内存连续算法会直接退出。需要在赋值时将stride赋值为实际占用内存长度如Y16数据位 w * 2RGB数据为w * 3**</font>
## 3 主接口与调用时序控制
相对于之前一个主接口打天下的方式,现阶段需要调用的接口增加。
- 接口使用前需要显式调用构造函数和初始化函数,使用完毕后手动析构函数。
- 由于AI识别技术的广泛使用 参考S727的实现将传统小面目标检测接口单独暴露出来供调用。目标列表融合部分需要针对每个项目需求编写。检测部分也受到整个算法模块的状态控制因此也需要在初始化完成后调用如对空对地模式参数。
框架如何响应外部指令。外部指令发出是瞬时的,在跟踪流程的任意时刻都有可能,但多目标跟踪过程中,批号、算法资源等都严重依赖上下帧关系,不能实时处理指令,从框架设计简易考虑,
需要在每一帧开始前进行统一的指令计算与响应。
因此本框架仍不支持实时响应,需要在下一帧统一处理。
### 3.4 锁定逻辑
跟踪算法最重要的外部接口是锁定逻辑,本框架中将锁定指令进行如下划分,作不同响应。
<font color=Red>接口1普通锁定</font>
```
void ARIDLL_LockCommand(ArithHandle hArithSrc, int nLockX, int nLockY, int nLockW, int nLockH)
```
- LockMode::LOCK_POINT
如果不传大小,则为点锁定,点锁定位置附近若存在目标,则自动锁定该目标,若点锁定附近无目标,则根据需求可执行不同操作,例如对空可进行强制提取,对地可进行固定波门锁定。
- LockMode::LOCK_RECT:
>如果传入完整的锁定框,那么仅执行强制面目标锁定。
<font color=Red>接口2引导锁定</font>
```
void ARIDLL_GuideLockMultiCommand(ArithHandle hArithSrc, TargetGuide* guideList, int num)
```
给出稳定系角度进行目标锁定,属于某种自动锁定逻辑,要求算法根据先验对视场内的目标进行智能化选择与锁定。同样支持多个目标。
引导锁定在接口形式上与普通锁定的点选比较接近,但一般点选是有人在回路的,锁错代价低,要求快速响应。引导锁定一般是个连续的自动流程,要求一次性锁对,可以延迟多帧处理。
```C++
STD_TRACKER_API void ARIDLL_AdjustTrackRect(ArithHandle hArithSrc,int dx,int dy,int dw,int dh);
```
修改锁定波门接口,可以在目标静止时微调已跟踪的目标框。接口是通过重复下发锁定实现的,因此不适合跟踪运动目标时使用。此外,由于在多目标场景下下发锁定一般会实现为再次初始化新目标,
因此本接口限制为仅单目标跟踪模式下有效。
**关于延迟跟踪机制**
该机制在跟踪调用端实现,可以降低算法设计的复杂度。
对于无线传输项目,显控端收到的图像往往是延迟的,用户在延迟的数据上下发跟踪,指令传到设备端后已无法确认指令要求的位置和图像。因此针对延迟跟踪项目,需要使用缓存队列+延迟跟踪设计。
正常跟踪时,算法调用者(综控)始终缓存图像帧(含内容与帧编号),显控端下发锁定指令时需附带帧编号,如果帧编号滞后于当前最新帧编号,则在缓存队列中查找用户锁定帧,并将送算法的队列指针指向该帧,同时根据帧差自适应跳帧速度,跟踪到最新帧后,则恢复正常跟踪。
## 4 状态与模式
本SDK目前定义了如下算法及需求相关的状态/模式,解释如下。
### 4.1外部系统模式 **GLB_SYS_MODE**
通常用于响应用户产品模式如S338用户定义的【战斗】【模靶】等S731自主定义的【无人值守】【扫描】等不一定都会影响算法状态和运行但通常都需将该模式传递给算法便于灵活响应不同的项目区别较大可能涉及接口增加。
### 4.2 算法内部状态 **GLB_STATUS**
算法根据用户需求,将自身工作状态进行划分。同时会针对不同控制指令自行切换。通常我司的光电设备具有 搜索 - 单目标跟踪 - 周扫 - 扇扫 - 多目标跟踪 - 丢失等状态。
根据下发的锁定指令或引导指令,算法会从不同的搜索状态转为跟踪,同时会输出自身当前状态,需要调用者外部及时接收并配合做出不同的响应(控制伺服、上报等)。
【搜索】
算法执行目标检测,并进行时空域滤波,送出具有固定批号的目标列表,该列表可以在如下结构中体现。
```c++
//*****目标检测*****(短时航迹点,用于用户指示)
int nAlarmObjCnts; //当前帧告警目标总个数
ARIDLL_OBJINFO stAlarmObjs[ST_OBJ_NUM]; //检测目标信息数组
```
【周扫】【扇扫】
与搜索状态基本一致,仅对目标出视场处理有所区别。
【跟踪】
跟踪一般是接收到锁定、引导或自动切换进入,进入跟踪状态后,将在如下结构中体现
```c++
//*****目标跟踪*****(长时航迹点第0个为主目标送伺服跟踪)
int nTrackObjCnts; //跟踪目标个数
ARIDLL_OBJINFO stTrackers[LT_OBJ_NUM]; //跟踪器输出数组
```
【待命】
一般不执行算法
【丢失】
跟踪状态下的子状态,表明跟踪器暂时无法发现目标,但没有放弃目标跟踪,仍保留了目标批号,此时需要将该状态透传给伺服控制,用于执行记忆跟踪。
一旦重捕目标成功,将从丢失重新回到跟踪状态。
### 4.3 场景模式 **GLB_SCEN_MODE**
指对空、对地、对海、实验室等场景的跟踪算法,由于场景不同,算法很难用相同的策略进行跟踪,因此为了保持良好的跟踪能力,在不同的场景下算法区分了实现,需要外部根据需要进行切换。通常项目中都允许进行手动切换或模式保持某种场景模式。
### 5 版本查询
NeoTacker的版本信息填写在不同模块的Version.h.in 文件中。包含构建时间和版本号。
```C++
#pragma once
#include <string>
std::string BUILD_TIME = "BUILD_TIME @build_time@";
std::string VERSION = "BUILD_VERSION 0.9.0";
```
其中版本号手动填写更新编译时间自动生成。利用Cmake进行构造时会自动将Version.h.in文件转为Version.h其中会将编译时间更换为当前时间。
编译完成后,通过如下指令可获取版本信息和编译时间。
![alt text](doc/images/imageVersion.png)
## 6.API 说明
### 6.1 构造
```C++
STD_TRACKER_API ArithHandle STD_CreatEOArithHandle();
```
ArithHandle 类型为void*,表示算法实例的指针,需要主动调用构造与析构,以此完成算法实例的生成与资源释放。
### 6.2 初始化
```C++
STD_TRACKER_API void ARIDLL_EOArithInit(ArithHandle hArith,int nWidth, int nHeight, GD_PIXEL_FORMAT_E nPixelType);
STD_TRACKER_API void ARIDLL_EOArithInitWithMode(ArithHandle hArith, int nWidth, int nHeight, GD_PIXEL_FORMAT_E nPixelType,
GLB_SYS_MODE nSysMode,GLB_SCEN_MODE nScenMode);
```
在调用后续接口前,需要完成初始化,否则后续接口将不能正常工作。可以调用默认初始化以及指定工作模式的初始化。
### 6.3 检测接口
```C++
STD_TRACKER_API TARGET_OBJECT* ARIDLL_SearchFrameTargets(ArithHandle hArithSrc, GD_VIDEO_FRAME_S img, int* nFrmTargetNum);
```
调用接口获取当前帧图像的传统目标检测队列,返回目标个数,以及目标队列。
传统检测算法与AI识别并行运行完成后调用者在 此处调用下面的接口可以合并二者输出。【可选】
```C++
STD_TRACKER_API int ARIDLL_MergeAITargets(ArithHandle hArithSrc, TARGET_OBJECT* pTargetArray,int num,obj_res* aiDetectArray,int aiNum);
```
合并后将AI识别与传统目标检测放在统一的数据结构中送入跟踪模块这里主要是处理字段的拷贝与溢出异常。
由于检测器通常与跟踪器并行,因此可能存在同时读写冲突,算法内部无锁,需调用者自行处理。
### 6.4 主接口
```C++
STD_TRACKER_API int ARIDLL_RunController(ArithHandle hArithSrc, GD_VIDEO_FRAME_S img, ARIDLL_INPUTPARA stInputPara, ARIDLL_OUTPUT* pstOutput);
```
```C++
#ifndef _ARIDLL_INPUTPARA_
#define _ARIDLL_INPUTPARA_
//输入【系统参数】结构体
typedef struct tagARIDLL_INPUTPARA
{
int nTimeStamp; //当前帧采集时刻时间戳,单位毫秒
int unFrmId; //当前帧图像帧编号
ServoInfo stServoInfo; //传感器伺服信息
CamInfo stCameraInfo; //相机信息
AirCraftInfo stAirCraftInfo; //载体信息
GuideInfo stGuideInfo; //外部引导信息
// 外部目标列表
int nInputTargetNum;
TARGET_OBJECT stInputTarget[INPUT_OBJ_NUM]; // 外部输入目标列表包含AI识别结果
// AI跟踪器结果
AIT_OUTPUT stAITrackerInfo;
}ARIDLL_INPUTPARA;
#endif
```
输入参数基本不需要介绍。
```C++
#ifndef _ARIDLL_OUTPUT_
#define _ARIDLL_OUTPUT_
//跟踪目标输出结构体
typedef struct tagARIDLL_OUTPUT
{
int nTimeStamp;//当前帧时间戳(透传),单位:毫秒
// 系统工作模式(透传)// by wcw04046 @ 2021/12/06
int nSysMode;
int nFrmNum;//处理帧计数
//*****工作状态*****
int nStatus; //待命/检测/跟踪/丢失状态信息等
//*****目标检测*****(短时航迹点,用于用户指示)
int nAlarmObjCnts; //当前帧告警目标总个数
ARIDLL_OBJINFO stAlarmObjs[ST_OBJ_NUM]; //检测目标信息数组
//*****目标跟踪*****(长时航迹点第0个为主目标送伺服跟踪)
int nTrackObjCnts; //跟踪目标个数
ARIDLL_OBJINFO stTrackers[LT_OBJ_NUM]; //跟踪器输出数组
// 以下为调试内容
// 事件处理信息
TRACK_EVENT stEventInfo;
// 算法控制指令计算透传来自API调用
GLB_PCCOMMAND stCommand;
// AI跟踪器协同控制指令输出,用于控制端侧NPU程序
AIT_Command stAI_TkCmd;
// 自定义输出---------
ARIDLL_DEBUG_OUTPUT stDebugInfo;
}ARIDLL_OUTPUT;
#endif
```
注意主接口返回的nSysMode表示的是凝视/扫描/自主工作等系统模式nStatus表示算法内部的搜索/跟踪/多目标跟踪等状态。
### 6.5 切换扫描/凝视/等系统模式
```C++
STD_TRACKER_API void ARIDLL_SetSysMode(ArithHandle hArithSrc, GLB_SYS_MODE nSysMode);
```
将算法在凝视/扇描/周扫等模式进行切换,算法行为有一定差异。
### 6.6 对空/对地场景模式切换
```C++
STD_TRACKER_API void ARIDLL_SetScenMode(ArithHandle hArithSrc, GLB_SCEN_MODE nScenMode);
```
算法切换为对空/对地/对海等场景模式切换后原跟踪目标自动解锁算法自动切入SEARCH状态。
### 6.7 锁定接口
```C++
STD_TRACKER_API void ARIDLL_LockCommand(ArithHandle hArithSrc, int nLockX,int nLockY,int nLockW,int nLockH);
```
调用后算法将从凝视尝试切换为跟踪状态,并输出锁定目标的位置。通过传参宽高可以选择点选或者框选,分别按照不同的项目需求进行锁定逻辑实现。
```C++
STD_TRACKER_API ARIDLL_OBJINFO ARIDLL_LockTarget(ArithHandle hArithSrc, GD_VIDEO_FRAME_S img, int nLockX, int nLockY, int nLockW, int nLockH);
```
该接口功能与ARIDLL_LockCommand 一致区别在于算法在当前帧完成锁定并将锁定目标传出来。传该目标的原因在锁定波门一般与用户设置或者识别结果相关传统跟踪器有最全面的参数和用户信息这样传统锁定结果可以供AI跟踪使用避免同时向AI跟踪传递重复的识别列表或者自定义波门等信息。
用该接口比上一个快1帧完成锁定适合目标快速运动场景捕获目标。
```C++
STD_TRACKER_API void ARIDLL_GuideLockMultiCommand(ArithHandle hArithSrc, TargetGuide* guideList,int num);
```
外引导转跟踪,可支持多批次的引导目标自动锁定。调用接口后算法等待目标进入视场(自动判断),并按照目标先验自动选择最佳目标进行跟踪。外部需监控算法状态,进入跟踪后即表明已锁定目标。
### 6.8 解除锁定
```C++
STD_TRACKER_API void ARIDLL_unLockCommand(ArithHandle hArithSrc);
```
调用后主接口返回的状态将变为搜索,跟踪器解锁。
### 6.9 算法参数设置
```C++
STD_TRACKER_API bool ARIDLL_SetRunTimeParam(ArithHandle hArithSrc, ARIDLL_PARMA config);
STD_TRACKER_API bool ARIDLL_GetRunTimeParam(ArithHandle hArithSrc, ARIDLL_PARMA* pConfig);
STD_TRACKER_API bool ARIDLL_ReadSetParamFile(ArithHandle hArithSrc, const char* configFilePath);
STD_TRACKER_API bool ARIDLL_ReadSetParamStream(ArithHandle hArithSrc,const char* configsstream);
```
算法参数获取与设置接口支持json配置文件文件路径或字符流下发以及结构体下发。
### 6.10 运行TLD接口
TLD在算法中通常占用了较长时间在某些帧频较高的系统中需要将TLD与主接口并行提高跟踪频率这样处理的代价是TLD的结果要在下一帧才能传递给主跟踪可能引起细微跟踪效果下降。标准基线中本接口是不调用的算法自行在内部运行了TLD。
一旦在外部调用该接口需要关闭算法内部的TLD运行因此调用该接口时需将输入的flag标记置为true以关闭内部调用。
```C++
STD_TRACKER_API void ARIDLL_RunTLDTracker(ArithHandle hArithSrc,GD_VIDEO_FRAME_S img);
```
### 6.11 析构
```C++
STD_TRACKER_API void STD_DeleteEOArithHandle(ArithHandle hArith);
```