进一步修改运动参数

main
wangchongwu 4 months ago
parent 65a2e8b7f6
commit cfb3caad1a

@ -3,7 +3,7 @@ SET(ArithTrkPubInc ${CMAKE_SOURCE_DIR}/public_include)
include_directories(${ArithTrkPubInc}) #
set(CMAKE_CXX_STANDARD 17)
#
add_subdirectory(tests)
add_subdirectory(profile)
IF(WIN32)
# vot_test

@ -0,0 +1,36 @@
message(STATUS "++++++++add Profile Test DIR++++++++")
# opencv
link_directories(${OpenCV_LIBS_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
#
SET(ArithTrkPubInc ${CMAKE_SOURCE_DIR}/public_include)
include_directories(${ArithTrkPubInc})
set(LIB_SRC_DIR ${CMAKE_SOURCE_DIR}/NeoTracker/src)
include_directories(${LIB_SRC_DIR})
link_directories(${CMAKE_SOURCE_DIR}/Bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/Bin)
# :使仿
add_executable(TestAPI_Profile TestAPI_Profile.cpp
Profile_SOT_Ground_NV12.cpp
Profile_SOT_Ground_Y16.cpp
Profile_SOT_Ground_Y8.cpp
Profile_SOT_Ground_RGB.cpp
Profile_SOT_Sky_Y16.cpp
Profile_SOT_LockUnlockStress.cpp
utils.cpp
)
target_link_libraries(TestAPI_Profile PRIVATE
${LIB_TRACKER}
${LIB_DETECTOR} #
${LIB_GDKCF} #KCF
${LIB_GDTLD} #TLD
${LIB_PIPE}
${OpenCV_LIBS})

@ -0,0 +1,128 @@
// NV12 对地跟踪性能测试
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
using std::cout;
using std::endl;
using std::string;
#define Test_Len 1000
int TestAPI_SOT_Ground_NV12()
{
// 产生一个仿真Y16数据
int nWidth = 1920;
int nHeight = 1080;
SimTargetImage factory(nWidth, nHeight);
factory.setBackGround(128, 10);
// 叠加一个初始目标
Target t;
t.x = 100;
t.y = 100;
t.width = 30;
t.height = 30;
t.vw = 0;
t.vh = 0;
t.vx = 1;
t.vy = 1;
t.addTexture(cow_png,cow_png_len);
factory.addTarget(t);
//
t.x = 300;
t.y = 250;
t.width = 100;
t.height = 100;
t.vw = 0;
t.vh = 0;
t.vx = 0;
t.vy = 0;
t.color = cv::Scalar(20,20,20);
factory.addOcc(t);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对地模式
ARIDLL_EOArithInitWithMode(pTracker,nWidth,nHeight,GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12,
GLB_SYS_MODE::GLB_SYS_STARE,GLB_SCEN_MODE::GLB_SCEN_GROUND);
// 算法输入部分
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
// 算法输出部分
ARIDLL_OUTPUT stOutput = { 0 };
// 模拟算法执行流程
int nTrackSuc = 0;
cv::Mat frame;
for(int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageNV12();
Target* gt = factory.getTarget(0);
// 构建图像类型
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width * 1;
img.u64VirAddr[0] = (unsigned char*)src.data;
// 下发面锁定指令
if (stInputPara.unFrmId == 3)
{
//ARIDLL_LockCommand(pTracker, gt->x,gt->y,gt->width,gt->height);
ARIDLL_LockCommand(pTracker, gt->x, gt->y, gt->width, gt->height);
}
cv::TickMeter tm;
tm.start();
// 运行算法主控逻辑API
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm.stop();
printf("time:%.2f\n",tm.getTimeMilli());
#ifdef SHOW
// 绘制跟踪结果
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb,&stOutput);
imshow("res",rgb);
cv::waitKey(1);
#endif
if (stOutput.nStatus == GLB_STATUS_TRACK && stOutput.nTrackObjCnts == 1)
{
if (abs(stOutput.stTrackers[0].nX - gt->x) < 5 &&
abs(stOutput.stTrackers[0].nY - gt->y) < 5)
{
nTrackSuc++;
}
}
}
printf("Suc:%d/A:%d\n",nTrackSuc,Test_Len);
return 0;
}

@ -0,0 +1,135 @@
// 单目标对地跟踪流程测试:将TLD从算法中剥离到外部导致API调用形式调整
// 读取avi视频进行测试
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
using std::cout;
using std::endl;
using std::string;
#define Test_Len 1000
int TestAPI_SOT_Ground_RGB()
{
// 产生一个仿真Y16数据
int nWidth = 1280;
int nHeight = 1024;
SimTargetImage factory(nWidth, nHeight);
factory.setBackGround(128, 10);
// 叠加一个初始目标
Target t;
t.x = 100;
t.y = 100;
t.width = 30;
t.height = 30;
t.vw = 0;
t.vh = 0;
t.vx = 1;
t.vy = 1;
t.addTexture(cow_png,cow_png_len);
factory.addTarget(t);
//
t.x = 300;
t.y = 250;
t.width = 100;
t.height = 100;
t.vw = 0;
t.vh = 0;
t.vx = 0;
t.vy = 0;
t.color = cv::Scalar(20,20,20);
factory.addOcc(t);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对地模式
ARIDLL_EOArithInitWithMode(pTracker,nWidth,nHeight,GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED,
GLB_SYS_MODE::GLB_SYS_STARE,GLB_SCEN_MODE::GLB_SCEN_GROUND);
// 算法输入部分
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
// 算法输出部分
ARIDLL_OUTPUT stOutput = { 0 };
// 模拟算法执行流程
int nTrackSuc = 0;
cv::Mat frame;
for(int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageRGB();
Target* gt = factory.getTarget(0);
// 构建图像类型
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_RGB_PACKED;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width * 3;
img.u64VirAddr[0] = (unsigned char*)src.data;
// 下发面锁定指令
if (stInputPara.unFrmId == 3)
{
ARIDLL_LockCommand(pTracker, gt->x,gt->y,gt->width,gt->height);
}
cv::TickMeter tm;
tm.start();
// 运行算法主控逻辑API
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm.stop();
printf("time:%.2f\n",tm.getTimeMilli());
#ifdef SHOW
// 绘制跟踪结果
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb,&stOutput);
imshow("res",rgb);
cv::waitKey(1);
#endif
if (stOutput.nStatus == GLB_STATUS_TRACK && stOutput.nTrackObjCnts == 1)
{
if (abs(stOutput.stTrackers[0].nX - gt->x) < 5 &&
abs(stOutput.stTrackers[0].nY - gt->y) < 5)
{
nTrackSuc++;
}
}
}
printf("Suc:%d/A:%d\n",nTrackSuc,Test_Len);
return 0;
}

@ -0,0 +1,135 @@
// 单目标对地跟踪流程测试:将TLD从算法中剥离到外部导致API调用形式调整
// 读取avi视频进行测试
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
using std::cout;
using std::endl;
using std::string;
#define Test_Len 1000
int TestAPI_SOT_Ground_Y16()
{
// 产生一个仿真Y16数据
int nWidth = 1280;
int nHeight = 1024;
SimTargetImage factory(nWidth, nHeight);
factory.setBackGround(128, 10);
// 叠加一个初始目标
Target t;
t.x = 100;
t.y = 100;
t.width = 30;
t.height = 30;
t.vw = 0;
t.vh = 0;
t.vx = 1;
t.vy = 1;
t.addTexture(cow_png,cow_png_len);
factory.addTarget(t);
//
t.x = 300;
t.y = 250;
t.width = 100;
t.height = 100;
t.vw = 0;
t.vh = 0;
t.vx = 0;
t.vy = 0;
t.color = cv::Scalar(20,20,20);
factory.addOcc(t);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对地模式
ARIDLL_EOArithInitWithMode(pTracker,nWidth,nHeight,GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16,
GLB_SYS_MODE::GLB_SYS_STARE,GLB_SCEN_MODE::GLB_SCEN_GROUND);
// 算法输入部分
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
// 算法输出部分
ARIDLL_OUTPUT stOutput = { 0 };
// 模拟算法执行流程
int nTrackSuc = 0;
cv::Mat frame;
for(int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageY16();
Target* gt = factory.getTarget(0);
// 构建图像类型
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width * 2;
img.u64VirAddr[0] = (unsigned char*)src.data;
// 下发面锁定指令
if (stInputPara.unFrmId == 3)
{
//ARIDLL_LockCommand(pTracker, gt->x,gt->y,gt->width,gt->height);
ARIDLL_LockCommand(pTracker, gt->x, gt->y, gt->width, gt->height);
}
cv::TickMeter tm;
tm.start();
// 运行算法主控逻辑API
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm.stop();
printf("time:%.2f\n",tm.getTimeMilli());
#ifdef SHOW
// 绘制跟踪结果
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb,&stOutput);
imshow("res",rgb);
cv::waitKey(1);
#endif
if (stOutput.nStatus == GLB_STATUS_TRACK && stOutput.nTrackObjCnts == 1)
{
if (abs(stOutput.stTrackers[0].nX - gt->x) < 5 &&
abs(stOutput.stTrackers[0].nY - gt->y) < 5)
{
nTrackSuc++;
}
}
}
printf("Suc:%d/A:%d\n",nTrackSuc,Test_Len);
return 0;
}

@ -0,0 +1,137 @@
// 单目标对地跟踪流程测试:将TLD从算法中剥离到外部导致API调用形式调整
// 读取avi视频进行测试
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
using std::cout;
using std::endl;
using std::string;
#define Test_Len 1000
int TestAPI_SOT_Ground_Y8()
{
// 产生一个仿真Y16数据
int nWidth = 1280;
int nHeight = 1024;
SimTargetImage factory(nWidth, nHeight);
factory.setBackGround(128, 10);
// 叠加一个初始目标
Target t;
t.x = 100;
t.y = 100;
t.width = 50;
t.height = 30;
t.vw = 0;
t.vh = 0;
t.vx = 0.3;
t.vy = 0.2;
t.color = cv::Scalar(25,255,1);
t.addTexture(cow_png,cow_png_len);
factory.addTarget(t);
t.x = 300;
t.y = 250;
t.width = 100;
t.height = 100;
t.vw = 0;
t.vh = 0;
t.vx = 0;
t.vy = 0;
t.color = cv::Scalar(20,20,20);
factory.addOcc(t);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对地模式
ARIDLL_EOArithInitWithMode(pTracker,nWidth,nHeight,GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8,
GLB_SYS_MODE::GLB_SYS_STARE,GLB_SCEN_MODE::GLB_SCEN_GROUND);
// 算法输入部分
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
// 算法输出部分
ARIDLL_OUTPUT stOutput = { 0 };
// 模拟算法执行流程
int nTrackSuc = 0;
cv::Mat frame;
for(int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageY8();
Target* gt = factory.getTarget(0);
// 构建图像类型
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y8;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width * 1;
img.u64VirAddr[0] = (unsigned char*)src.data;
// 下发面锁定指令
if (stInputPara.unFrmId == 3)
{
ARIDLL_LockCommand(pTracker, gt->x,gt->y,gt->width,gt->height);
}
cv::TickMeter tm;
tm.start();
// 运行算法主控逻辑API
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm.stop();
printf("time:%.2f\n",tm.getTimeMilli());
#ifdef SHOW
// 绘制跟踪结果
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb,&stOutput);
imshow("res",rgb);
cv::waitKey(1);
#endif
if (stOutput.nStatus == GLB_STATUS_TRACK && stOutput.nTrackObjCnts == 1)
{
if (abs(stOutput.stTrackers[0].nX - gt->x) < 5 &&
abs(stOutput.stTrackers[0].nY - gt->y) < 5)
{
nTrackSuc++;
}
}
}
printf("Suc:%d/A:%d\n",nTrackSuc,Test_Len);
return 0;
}

@ -0,0 +1,118 @@
// 暴力锁定解锁鲁棒性测试
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
#include <random>
using std::cout;
using std::endl;
int TestAPI_SOT_LockUnlock_Stress()
{
// 产生一个仿真数据
int nWidth = 1920;
int nHeight = 1080;
const int Test_Len = 100000;
// 初始化随机数生成器
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> offsetDist(-2000, 2000); // 在目标周围±5像素范围内随机
SimTargetImage factory(nWidth, nHeight);
factory.setCheckerboardBackGround(120, 0, 80);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对空模式
ARIDLL_EOArithInitWithMode(pTracker, nWidth, nHeight, GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12,
GLB_SYS_MODE::GLB_SYS_STARE, GLB_SCEN_MODE::GLB_SCEN_GROUND);
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.unFreq = 50;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
stInputPara.stCameraInfo.unVideoType = GLB_VIDEO_IR_MW;
ARIDLL_OUTPUT stOutput = { 0 };
// 生成随机锁定解锁序列
std::vector<int> lockUnlockSequence = generateRandomLockUnlockSequence(Test_Len);
int nTrackSuc = 0;
int nLock = 0, nUnlock = 0, nLost = 0;
bool locked = false;
for (int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageNV12();
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_NV12;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width;
img.u64VirAddr[0] = (UBYTE8*)src.data;
int targetNum = 0;
cv::TickMeter tm1;
tm1.start();
{
//targetNum = ARIDLL_SearchFrameTargets(pTracker, img);
}
tm1.stop();
printf("det time:%.2f", tm1.getTimeMilli());
// 根据序列执行锁定/解锁操作
switch (lockUnlockSequence[i])
{
case 1: // 锁定
{
// 在目标周围随机选择锁定位置
int offsetX = offsetDist(gen);
int offsetY = offsetDist(gen);
//ARIDLL_LockCommand_DefaultSize(pTracker, (int)nWidth / 2 + offsetX, (int)nHeight / 2 + offsetY, 30, 30);
//ARIDLL_LockTarget_DefaultSize(pTracker, img,(int)nWidth / 2 + offsetX, (int)nHeight / 2 + offsetY, 30, 30);
locked = true;
nLock++;
}
break;
case 2: // 解锁
ARIDLL_unLockCommand(pTracker);
locked = false;
nUnlock++;
break;
default: // 普通帧
break;
}
cv::TickMeter tm2;
tm2.start();
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm2.stop();
printf(" trk time:%.2f\n", tm2.getTimeMilli());
#ifdef SHOW
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb, &stOutput);
imshow("res", rgb);
cv::waitKey(1);
#endif
printf("nStatus:%d,Proc:%d", stOutput.nStatus,stInputPara.unFrmId);
}
// 输出测试统计结果
return 0;
}

@ -0,0 +1,148 @@
// 单目标对空跟踪流程测试关注跟踪器FPS
#include "NeoArithStandardDll.h"
#include "utils.h"
#include <iostream>
#include <memory>
#include <string.h>
#include <algorithm>
#include <thread>
#include "opencv2/opencv.hpp"
#include "TestAPI_Profile.h"
using std::cout;
using std::endl;
#define Test_Len 1000
int TestAPI_SOT_Sky_Y16()
{
// 产生一个仿真Y16数据
int nWidth = 640;
int nHeight = 512;
SimTargetImage factory(nWidth, nHeight);
factory.setBackGround(120, 0);
// 叠加一个初始目标
Target t;
t.x = 100;
t.y = 100;
t.width = 4;
t.height = 4;
t.vw = 0;
t.vh = 0;
t.vx = 1;
t.vy = 1;
t.color = cv::Scalar(255,255,255);
t.vc = 10;
//t.addTexture(cow_png, cow_png_len);
//t.bGrayComplex = true;
//t.color2 = cv::Scalar(10, 10, 10);
factory.addTarget(t);
// 创建算法句柄
ArithHandle pTracker = STD_CreatEOArithHandle();
// 初始化为凝视-对空模式
ARIDLL_EOArithInitWithMode(pTracker,nWidth,nHeight,GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16,
GLB_SYS_MODE::GLB_SYS_STARE,GLB_SCEN_MODE::GLB_SCEN_SKY);
// 算法输入部分
ARIDLL_INPUTPARA stInputPara = { 0 };
stInputPara.unFrmId++;
stInputPara.unFreq = 50;
stInputPara.stCameraInfo.fPixelSize = 15;
stInputPara.stCameraInfo.nFocus = 300;
stInputPara.stCameraInfo.unVideoType = GLB_VIDEO_IR_MW;
// 算法输出部分
ARIDLL_OUTPUT stOutput = { 0 };
// 模拟算法执行流程
int nTrackSuc = 0;
for (int i = 0; i < Test_Len; i++)
{
stInputPara.unFrmId++;
factory.update();
cv::Mat src = factory.getImageY16();
Target* gt = factory.getTarget(0);
// 下发点锁定指令
if (i == 50)
{
ARIDLL_LockCommand(pTracker, (int)gt->x, (int)gt->y,0,0);
}
// 构建图像类型
GD_VIDEO_FRAME_S img = { 0 };
img.enPixelFormat = GD_PIXEL_FORMAT_E::GD_PIXEL_FORMAT_GRAY_Y16;
img.u32Width = nWidth;
img.u32Height = nHeight;
img.u32Stride[0] = img.u32Width * 2;
img.u64VirAddr[0] = (UBYTE8*)src.data;
// 红外目标检测API调用
int targetNum = 0;
// 目标搜索仅在搜索状态执行,保持与经典对空算法一致,用于与上一版本耗时对比
// 新跟踪器中搜索在单独线程中不间断执行本demo中仅展示用法不做并行示范。
//if (stOutput.nStatus == GLB_STATUS_SEARCH)
cv::TickMeter tm1;
tm1.start();
{
targetNum = ARIDLL_SearchFrameTargets(pTracker, img);
}
tm1.stop();
printf("det time:%.2f", tm1.getTimeMilli());
cv::TickMeter tm2;
tm2.start();
// 运行算法主控逻辑API
ARIDLL_RunController(pTracker, img, stInputPara, &stOutput);
tm2.stop();
printf(" trk time:%.2f\n", tm2.getTimeMilli());
//std::cout << gt->x << " " << gt->y << std::endl;
#ifdef SHOW
// 绘制跟踪结果
cv::Mat rgb = factory.getImageRGB();
showArithInfo(rgb,&stOutput);
imshow("res",rgb);
cv::waitKey(1);
#endif
if (stOutput.nStatus == GLB_STATUS_TRACK && stOutput.nTrackObjCnts == 1)
{
if (abs(stOutput.stTrackers[0].nX - gt->x) < 5 &&
abs(stOutput.stTrackers[0].nY - gt->y) < 5)
{
nTrackSuc++;
}
}
}
if (nTrackSuc > Test_Len * 0.9)
{
cout << "pass" << endl;
}
printf("Suc:%d/A:%d\n",nTrackSuc,Test_Len);
return 0;
}

@ -0,0 +1,17 @@
# 单元测试为基础的性能和功能测试
test 中包含的内容为基准性能测试和最简单的功能测试。主要用于不同平台下耗时统计。
使用方式:
./TestAPI_Profile -s ground -d NV12
- 使用了cmdline进行参数解析
- 使用lambda进行参数与测试接口绑定减少可执行程序个数。
- 内置一个功能较为完整的目标图像仿真模块,可以制作出贴图目标的遮挡、放缩、运动等效果而不需要依赖外部视频或者贴图。
- 根据项目和硬件需要自由增加测试项。
- test项不再执行其他性能测试。

@ -0,0 +1,55 @@
#include "cmdline.h"//命令行解析
#include <functional>
#include <unordered_map>
#include <iostream>
#include "image_data.h"
#include "TestAPI_Profile.h"
using namespace std;
int main(int argc, char *argv[])
{
TestAPI_SOT_Sky_Y16();
return 0;
// 映射表
std::unordered_map<std::string, std::function<void()>> handlerMap = {
{"sky:Y16", TestAPI_SOT_Sky_Y16},
{"ground:Y8", TestAPI_SOT_Ground_Y8},
{"ground:RGB", TestAPI_SOT_Ground_RGB},
{"ground:Y16", TestAPI_SOT_Ground_Y16},
{"ground:NV12", TestAPI_SOT_Ground_NV12},
{"ground:NV12:LOCK_STRESS", TestAPI_SOT_LockUnlock_Stress},
};
cmdline::parser a;
a.add<string>("scen",'s',"sky or ground",true,"");
a.add<string>("dataType",'d',"Y8/Y16/RGB/NV12",true,"");
a.add<string>("testItem",'t',"other item",false,"");
a.parse_check(argc, argv);
cout << "scen:" << a.get<string>("scen")
<< "datatype:" << a.get<string>("dataType") << endl;
cout << "------------------ " << endl;
std::string scen = a.get<std::string>("scen");
std::string dataType = a.get<std::string>("dataType");
std::string testItem = a.get<std::string>("testItem");
std::string key;
if (!testItem.empty()) {
key = scen + ":" + dataType + ":" + testItem;
} else {
key = scen + ":" + dataType;
}
// 查找并执行逻辑
if (handlerMap.find(key) != handlerMap.end()) {
handlerMap[key]();
} else {
std::cout << "Invalid combination of scen and dataType: " << key << std::endl;
}
return 0;
}

@ -0,0 +1,13 @@
#include "utils.h"
#define SHOW
extern unsigned char cow_png[];
extern unsigned int cow_png_len;
int TestAPI_SOT_Ground_NV12();
int TestAPI_SOT_Ground_RGB();
int TestAPI_SOT_Ground_Y8();
int TestAPI_SOT_Ground_Y16();
int TestAPI_SOT_Sky_Y16();
int TestAPI_SOT_LockUnlock_Stress();

@ -0,0 +1,821 @@
/*
Copyright (c) 2009, Hideyuki Tanaka
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <iostream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
#include <stdexcept>
#include <typeinfo>
#include <cstring>
#include <algorithm>
#ifdef __GNUC__
#include <cxxabi.h>
#endif
#include <cstdlib>
namespace cmdline{
namespace detail{
template <typename Target, typename Source, bool Same>
class lexical_cast_t{
public:
static Target cast(const Source &arg){
Target ret;
std::stringstream ss;
if (!(ss<<arg && ss>>ret && ss.eof()))
throw std::bad_cast();
return ret;
}
};
template <typename Target, typename Source>
class lexical_cast_t<Target, Source, true>{
public:
static Target cast(const Source &arg){
return arg;
}
};
template <typename Source>
class lexical_cast_t<std::string, Source, false>{
public:
static std::string cast(const Source &arg){
std::ostringstream ss;
ss<<arg;
return ss.str();
}
};
template <typename Target>
class lexical_cast_t<Target, std::string, false>{
public:
static Target cast(const std::string &arg){
Target ret;
std::istringstream ss(arg);
if (!(ss>>ret && ss.eof()))
throw std::bad_cast();
return ret;
}
};
template <typename T1, typename T2>
struct is_same {
static const bool value = false;
};
template <typename T>
struct is_same<T, T>{
static const bool value = true;
};
template<typename Target, typename Source>
Target lexical_cast(const Source &arg)
{
return lexical_cast_t<Target, Source, detail::is_same<Target, Source>::value>::cast(arg);
}
static inline std::string demangle(const std::string &name)
{
#ifdef _MSC_VER
return name; // 为MSVC编译器时直接返回name
#elif defined(__GNUC__)
// 为gcc编译器时还调用原来的代码
int status = 0;
char* p = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
std::string ret(p);
free(p);
return ret;
#else
// 其他不支持的编译器需要自己实现这个方法
#error unexpected c complier (msc/gcc), Need to implement this method for demangle
#endif
}
template <class T>
std::string readable_typename()
{
return demangle(typeid(T).name());
}
template <class T>
std::string default_value(T def)
{
return detail::lexical_cast<std::string>(def);
}
template <>
inline std::string readable_typename<std::string>()
{
return "string";
}
} // detail
//-----
class cmdline_error : public std::exception {
public:
cmdline_error(const std::string &msg): msg(msg){}
~cmdline_error() throw() {}
const char *what() const throw() { return msg.c_str(); }
private:
std::string msg;
};
template <class T>
struct default_reader{
T operator()(const std::string &str){
return detail::lexical_cast<T>(str);
}
};
template <class T>
struct range_reader{
range_reader(const T &low, const T &high): low(low), high(high) {}
T operator()(const std::string &s) const {
T ret=default_reader<T>()(s);
if (!(ret>=low && ret<=high)) throw cmdline::cmdline_error("range_error");
return ret;
}
private:
T low, high;
};
template <class T>
range_reader<T> range(const T &low, const T &high)
{
return range_reader<T>(low, high);
}
template <class T>
struct oneof_reader{
T operator()(const std::string &s){
T ret=default_reader<T>()(s);
if (std::find(alt.begin(), alt.end(), ret)==alt.end())
throw cmdline_error("");
return ret;
}
void add(const T &v){ alt.push_back(v); }
private:
std::vector<T> alt;
};
template <class T>
oneof_reader<T> oneof(T a1)
{
oneof_reader<T> ret;
ret.add(a1);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
ret.add(a6);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
ret.add(a6);
ret.add(a7);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
ret.add(a6);
ret.add(a7);
ret.add(a8);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
ret.add(a6);
ret.add(a7);
ret.add(a8);
ret.add(a9);
return ret;
}
template <class T>
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9, T a10)
{
oneof_reader<T> ret;
ret.add(a1);
ret.add(a2);
ret.add(a3);
ret.add(a4);
ret.add(a5);
ret.add(a6);
ret.add(a7);
ret.add(a8);
ret.add(a9);
ret.add(a10);
return ret;
}
//-----
class parser{
public:
parser(){
}
~parser(){
for (std::map<std::string, option_base*>::iterator p=options.begin();
p!=options.end(); p++)
delete p->second;
}
void add(const std::string &name,
char short_name=0,
const std::string &desc=""){
if (options.count(name)) throw cmdline_error("multiple definition: "+name);
options[name]=new option_without_value(name, short_name, desc);
ordered.push_back(options[name]);
}
template <class T>
void add(const std::string &name,
char short_name=0,
const std::string &desc="",
bool need=true,
const T def=T()){
add(name, short_name, desc, need, def, default_reader<T>());
}
template <class T, class F>
void add(const std::string &name,
char short_name=0,
const std::string &desc="",
bool need=true,
const T def=T(),
F reader=F()){
if (options.count(name)) throw cmdline_error("multiple definition: "+name);
options[name]=new option_with_value_with_reader<T, F>(name, short_name, need, def, desc, reader);
ordered.push_back(options[name]);
}
void footer(const std::string &f){
ftr=f;
}
void set_program_name(const std::string &name){
prog_name=name;
}
bool exist(const std::string &name) const {
if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name);
return options.find(name)->second->has_set();
}
template <class T>
const T &get(const std::string &name) const {
if (options.count(name)==0) throw cmdline_error("there is no flag: --"+name);
const option_with_value<T> *p=dynamic_cast<const option_with_value<T>*>(options.find(name)->second);
if (p==NULL) throw cmdline_error("type mismatch flag '"+name+"'");
return p->get();
}
const std::vector<std::string> &rest() const {
return others;
}
bool parse(const std::string &arg){
std::vector<std::string> args;
std::string buf;
bool in_quote=false;
for (std::string::size_type i=0; i<arg.length(); i++){
if (arg[i]=='\"'){
in_quote=!in_quote;
continue;
}
if (arg[i]==' ' && !in_quote){
args.push_back(buf);
buf="";
continue;
}
if (arg[i]=='\\'){
i++;
if (i>=arg.length()){
errors.push_back("unexpected occurrence of '\\' at end of string");
return false;
}
}
buf+=arg[i];
}
if (in_quote){
errors.push_back("quote is not closed");
return false;
}
if (buf.length()>0)
args.push_back(buf);
for (size_t i=0; i<args.size(); i++)
std::cout<<"\""<<args[i]<<"\""<<std::endl;
return parse(args);
}
bool parse(const std::vector<std::string> &args){
int argc=static_cast<int>(args.size());
std::vector<const char*> argv(argc);
for (int i=0; i<argc; i++)
argv[i]=args[i].c_str();
return parse(argc, &argv[0]);
}
bool parse(int argc, const char * const argv[]){
errors.clear();
others.clear();
if (argc<1){
errors.push_back("argument number must be longer than 0");
return false;
}
if (prog_name=="")
prog_name=argv[0];
std::map<char, std::string> lookup;
for (std::map<std::string, option_base*>::iterator p=options.begin();
p!=options.end(); p++){
if (p->first.length()==0) continue;
char initial=p->second->short_name();
if (initial){
if (lookup.count(initial)>0){
lookup[initial]="";
errors.push_back(std::string("short option '")+initial+"' is ambiguous");
return false;
}
else lookup[initial]=p->first;
}
}
for (int i=1; i<argc; i++){
if (strncmp(argv[i], "--", 2)==0){
const char *p=strchr(argv[i]+2, '=');
if (p){
std::string name(argv[i]+2, p);
std::string val(p+1);
set_option(name, val);
}
else{
std::string name(argv[i]+2);
if (options.count(name)==0){
errors.push_back("undefined option: --"+name);
continue;
}
if (options[name]->has_value()){
if (i+1>=argc){
errors.push_back("option needs value: --"+name);
continue;
}
else{
i++;
set_option(name, argv[i]);
}
}
else{
set_option(name);
}
}
}
else if (strncmp(argv[i], "-", 1)==0){
if (!argv[i][1]) continue;
char last=argv[i][1];
for (int j=2; argv[i][j]; j++){
last=argv[i][j];
if (lookup.count(argv[i][j-1])==0){
errors.push_back(std::string("undefined short option: -")+argv[i][j-1]);
continue;
}
if (lookup[argv[i][j-1]]==""){
errors.push_back(std::string("ambiguous short option: -")+argv[i][j-1]);
continue;
}
set_option(lookup[argv[i][j-1]]);
}
if (lookup.count(last)==0){
errors.push_back(std::string("undefined short option: -")+last);
continue;
}
if (lookup[last]==""){
errors.push_back(std::string("ambiguous short option: -")+last);
continue;
}
if (i+1<argc && options[lookup[last]]->has_value()){
set_option(lookup[last], argv[i+1]);
i++;
}
else{
set_option(lookup[last]);
}
}
else{
others.push_back(argv[i]);
}
}
for (std::map<std::string, option_base*>::iterator p=options.begin();
p!=options.end(); p++)
if (!p->second->valid())
errors.push_back("need option: --"+std::string(p->first));
return errors.size()==0;
}
void parse_check(const std::string &arg){
if (!options.count("help"))
add("help", '?', "print this message");
check(0, parse(arg));
}
void parse_check(const std::vector<std::string> &args){
if (!options.count("help"))
add("help", '?', "print this message");
check(args.size(), parse(args));
}
void parse_check(int argc, char *argv[]){
if (!options.count("help"))
add("help", '?', "print this message");
check(argc, parse(argc, argv));
}
std::string error() const{
return errors.size()>0?errors[0]:"";
}
std::string error_full() const{
std::ostringstream oss;
for (size_t i=0; i<errors.size(); i++)
oss<<errors[i]<<std::endl;
return oss.str();
}
std::string usage() const {
std::ostringstream oss;
oss<<"usage: "<<prog_name<<" ";
for (size_t i=0; i<ordered.size(); i++){
if (ordered[i]->must())
oss<<ordered[i]->short_description()<<" ";
}
oss<<"[options] ... "<<ftr<<std::endl;
oss<<"options:"<<std::endl;
size_t max_width=0;
for (size_t i=0; i<ordered.size(); i++){
max_width=std::max(max_width, ordered[i]->name().length());
}
for (size_t i=0; i<ordered.size(); i++){
if (ordered[i]->short_name()){
oss<<" -"<<ordered[i]->short_name()<<", ";
}
else{
oss<<" ";
}
oss<<"--"<<ordered[i]->name();
for (size_t j=ordered[i]->name().length(); j<max_width+4; j++)
oss<<' ';
oss<<ordered[i]->description()<<std::endl;
}
return oss.str();
}
private:
void check(int argc, bool ok){
if ((argc==1 && !ok) || exist("help")){
std::cerr<<usage();
exit(0);
}
if (!ok){
std::cerr<<error()<<std::endl<<usage();
exit(1);
}
}
void set_option(const std::string &name){
if (options.count(name)==0){
errors.push_back("undefined option: --"+name);
return;
}
if (!options[name]->set()){
errors.push_back("option needs value: --"+name);
return;
}
}
void set_option(const std::string &name, const std::string &value){
if (options.count(name)==0){
errors.push_back("undefined option: --"+name);
return;
}
if (!options[name]->set(value)){
errors.push_back("option value is invalid: --"+name+"="+value);
return;
}
}
class option_base{
public:
virtual ~option_base(){}
virtual bool has_value() const=0;
virtual bool set()=0;
virtual bool set(const std::string &value)=0;
virtual bool has_set() const=0;
virtual bool valid() const=0;
virtual bool must() const=0;
virtual const std::string &name() const=0;
virtual char short_name() const=0;
virtual const std::string &description() const=0;
virtual std::string short_description() const=0;
};
class option_without_value : public option_base {
public:
option_without_value(const std::string &name,
char short_name,
const std::string &desc)
:nam(name), snam(short_name), desc(desc), has(false){
}
~option_without_value(){}
bool has_value() const { return false; }
bool set(){
has=true;
return true;
}
bool set(const std::string &){
return false;
}
bool has_set() const {
return has;
}
bool valid() const{
return true;
}
bool must() const{
return false;
}
const std::string &name() const{
return nam;
}
char short_name() const{
return snam;
}
const std::string &description() const {
return desc;
}
std::string short_description() const{
return "--"+nam;
}
private:
std::string nam;
char snam;
std::string desc;
bool has;
};
template <class T>
class option_with_value : public option_base {
public:
option_with_value(const std::string &name,
char short_name,
bool need,
const T &def,
const std::string &desc)
: nam(name), snam(short_name), need(need), has(false)
, def(def), actual(def) {
this->desc=full_description(desc);
}
~option_with_value(){}
const T &get() const {
return actual;
}
bool has_value() const { return true; }
bool set(){
return false;
}
bool set(const std::string &value){
try{
actual=read(value);
has=true;
}
catch(const std::exception &e){
return false;
}
return true;
}
bool has_set() const{
return has;
}
bool valid() const{
if (need && !has) return false;
return true;
}
bool must() const{
return need;
}
const std::string &name() const{
return nam;
}
char short_name() const{
return snam;
}
const std::string &description() const {
return desc;
}
std::string short_description() const{
return "--"+nam+"="+detail::readable_typename<T>();
}
protected:
std::string full_description(const std::string &desc){
return
desc+" ("+detail::readable_typename<T>()+
(need?"":" [="+detail::default_value<T>(def)+"]")
+")";
}
virtual T read(const std::string &s)=0;
std::string nam;
char snam;
bool need;
std::string desc;
bool has;
T def;
T actual;
};
template <class T, class F>
class option_with_value_with_reader : public option_with_value<T> {
public:
option_with_value_with_reader(const std::string &name,
char short_name,
bool need,
const T def,
const std::string &desc,
F reader)
: option_with_value<T>(name, short_name, need, def, desc), reader(reader){
}
private:
T read(const std::string &s){
return reader(s);
}
F reader;
};
std::map<std::string, option_base*> options;
std::vector<option_base*> ordered;
std::string ftr;
std::string prog_name;
std::vector<std::string> others;
std::vector<std::string> errors;
};
} // cmdline

File diff suppressed because it is too large Load Diff

@ -0,0 +1 @@
./TestAPI_Profile "-s" "sky" "-d" "Y16"

@ -0,0 +1,398 @@
#include <memory>
#include "utils.h"
#include "opencv2/opencv.hpp"
#include <random> // 添加随机数生成相关头文件
using namespace std;
using namespace cv;
SimTargetImage_Y16::SimTargetImage_Y16(int w, int h)
{
pSrc = new unsigned short[w * h];
Y8Mat = cv::Mat(h,w,CV_8UC1);
nImageWidth = w;
nImageHeight = h;
}
SimTargetImage_Y16::~SimTargetImage_Y16()
{
if (pSrc)
{
delete[]pSrc;
pSrc = nullptr;
}
}
void SimTargetImage_Y16::setBackGround(int gray, int std)
{
for (size_t i = 0; i < nImageHeight; i++)
{
for (size_t j = 0; j < nImageWidth; j++)
{
pSrc[i * nImageWidth + j] = rand() % std + gray;
}
}
}
void SimTargetImage_Y16::addTarget(int x, int y, int w, int h, int gray)
{
for (size_t i = y - h/2; i < y + h/2; i++)
{
for (size_t j = x - w/2; j < x+w/2; j++)
{
pSrc[i * nImageWidth + j] = gray;
}
}
}
unsigned short* SimTargetImage_Y16::getImageData()
{
return pSrc;
}
cv::Mat SimTargetImage_Y16::getMatRGB()
{
Map16BitTo8Bit(pSrc, nImageHeight * nImageWidth, Y8Mat.data);
cv::Mat rgb;
cv::cvtColor(Y8Mat,rgb,COLOR_GRAY2RGB);
return rgb.clone();
}
SimTargetImage::SimTargetImage(int w,int h)
{
m_BaseMat = cv::Mat(h,w,CV_8UC3);
m_CurMat = m_BaseMat.clone();
m_imgW = w;
m_imgH = h;
}
void SimTargetImage::update()
{
m_CurMat = m_BaseMat.clone();
// 绘制目标
for (int i = 0; i < m_targetList.size(); ++i)
{
Target* target = &m_targetList[i];
// 更新目标位置
target->updatePosition(m_imgW, m_imgH);
target->updateTexture();
//target->color = cv::Scalar(target->color[0] + target->vc, target->color[0] + target->vc, target->color[0] + target->vc);
drawObj(*target);
}
// 绘制遮挡
for (int i = 0; i < m_OccList.size(); ++i)
{
Target* target = &m_OccList[i];
// 绘制目标
drawOcc(*target);
}
}
void SimTargetImage::setBackGround(int gray, int std)
{
cv::Mat noise(m_BaseMat.size(), CV_8UC3);
cv::randn(noise, cv::Scalar::all(gray), cv::Scalar::all(std)); // 高斯噪声
m_BaseMat = noise;
m_CurMat = noise.clone();
}
void SimTargetImage::addTarget(Target t)
{
m_targetList.push_back(t);
}
void SimTargetImage::addOcc(Target t)
{
m_OccList.push_back(t);
}
cv::Mat SimTargetImage::getImageRGB()
{
return m_CurMat;
}
cv::Mat SimTargetImage::getImageY16()
{
cvtColor(m_CurMat,matY8,COLOR_BGR2GRAY);
matY8.convertTo(matY16,CV_16UC1);
return matY16*3+4000;
}
cv::Mat SimTargetImage::getImageY8()
{
cvtColor(m_CurMat,matY8,COLOR_BGR2GRAY);
return matY8;
}
cv::Mat SimTargetImage::getImageNV12()
{
matNV12 = cv::Mat(m_imgH*1.5, m_imgW, CV_8UC1);
cv::Mat matYUV_I420(m_imgH*1.5, m_imgW, CV_8UC1);
cvtColor(m_CurMat, matYUV_I420, COLOR_BGR2YUV_I420);
int nLenY = m_imgW * m_imgH;
int nLenU = nLenY / 4;
uchar* pNV12 = matNV12.data;
uchar* pUV = matNV12.data + nLenY;
uchar* pI420 = matYUV_I420.data;
memcpy(pNV12, pI420, nLenY);
for (int i = 0; i < nLenU; i++)
{
pUV[2 * i] = pI420[nLenY + i]; // U
pUV[2 * i + 1] = pI420[nLenY + nLenU + i]; // V
}
return matNV12;
}
Target* SimTargetImage::getTarget(int id)
{
if (m_targetList.size() > 0)
{
return &m_targetList[id];
}
else
{
return nullptr;
}
}
void SimTargetImage::drawObj(Target t)
{
if (t.useTexture)
{
// 设置叠加位置
int offsetX = t.x - t.width/2, offsetY = t.y - t.height/2;
cv::Rect roi(offsetX, offsetY, t.width, t.height);
// // 将前景叠加到背景,使用 Alpha 通道作为掩码
t.texture_cur.copyTo(m_CurMat(roi),t.alaph_cur);
return;
}
if (t.bGrayComplex)
{
cv::Rect rect(t.x - t.width / 2, t.y - t.height / 2, t.width, t.height/2);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
cv::Rect rect2(t.x - t.width / 2, t.y - t.height / 4, t.width, t.height/2);
cv::rectangle(m_CurMat, rect2, cv::Scalar(t.color2), cv::FILLED);
}
else
{
cv::Rect rect(t.x - t.width / 2, t.y - t.height / 2, t.width, t.height);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
}
}
void SimTargetImage::drawOcc(Target t)
{
cv::Rect rect(t.x - t.width/2, t.y - t.height/2, t.width, t.height);
cv::rectangle(m_CurMat, rect, cv::Scalar(t.color), cv::FILLED);
}
void SimTargetImage::setCheckerboardBackGround(int gray1, int gray2, int blockSize)
{
m_BaseMat = cv::Mat(m_imgH, m_imgW, CV_8UC3);
for (int y = 0; y < m_imgH; ++y)
{
for (int x = 0; x < m_imgW; ++x)
{
int bx = x / blockSize;
int by = y / blockSize;
bool isWhite = (bx + by) % 2 == 0;
int gray = isWhite ? gray1 : gray2;
m_BaseMat.at<cv::Vec3b>(y, x) = cv::Vec3b(gray, gray, gray);
}
}
m_CurMat = m_BaseMat.clone();
}
void Map16BitTo8Bit(unsigned short* psh16BitData, long lDataLen, unsigned char* pby8BitData)
{
if (psh16BitData == NULL || pby8BitData == NULL || lDataLen <= 0)
{
return;
}
//指向直方图的数据指针
int* pHist = new int[65536];
memset(pHist, 0, 65536 * sizeof(int));
int i = 0;
for (i = 0; i < lDataLen; i += 10)
{
pHist[psh16BitData[i]]++;
}
//设置阈值大小为: AreaSigma*图象大小/100
int nSigma = (int)(0.03 * lDataLen);
int nSum = 0;
int nMin = 0;
int nMax = 0;
//求映射的最大最小值
for (i = 0; i < 65536; i++)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMin = i;
break;
}
}
nSum = 0;
for (i = 65535; i >= 0; i--)
{
nSum += pHist[i];
if (nSum >= nSigma)
{
nMax = i;
break;
}
}
//计算对比度亮度
float K = (float)(120.0 / (nMax - nMin + 1));
float C = (float)(-K * nMin);
//图像映射
for (i = 0; i < lDataLen; i++)
{
int nValue = (int)(K * psh16BitData[i] + C);
if (nValue < 0)
{
pby8BitData[i] = 0;
}
else if (nValue > 255)
{
pby8BitData[i] = 255;
}
else
{
pby8BitData[i] = nValue;
}
}
delete[] pHist;
}
void showArithInfo(cv::Mat src, ARIDLL_OUTPUT * stOutput)
{
auto detNum = stOutput->nAlarmObjCnts;
auto detObjs = stOutput->stAlarmObjs;
for (size_t i = 0; i < detNum; i++)
{
cv::Rect outRect;
outRect.width = MAX(15,int(detObjs[i].nObjW));
outRect.height= MAX(15,int(detObjs[i].nObjH));
outRect.x = detObjs[i].nX-outRect.width/2.0;
outRect.y = detObjs[i].nY-outRect.height/2.0;
cv::rectangle(src,outRect,cv::Scalar(255,0,0),2);
cv::putText(src,to_string(detObjs[i].nOutputID),cv::Point(outRect.x - 10,outRect.y),1,2,cv::Scalar(255,255,0));
}
auto trackerOut = stOutput->stTrackers[0];
cv::Rect outRect;
outRect.width = MAX(25,int(trackerOut.nObjW));
outRect.height= MAX(25,int(trackerOut.nObjH));
outRect.x = trackerOut.nX-outRect.width/2.0;
outRect.y = trackerOut.nY-outRect.height/2.0;
cv::rectangle(src,outRect,cv::Scalar(0,0,255),2);
char str[100];
sprintf(str,"%d,%d,%d,%d",int(trackerOut.nX),int(trackerOut.nY),int(trackerOut.nObjW),int(trackerOut.nObjH));
cv::putText(src,cv::String(str),cv::Point(outRect.x - 10,outRect.y),1,2,cv::Scalar(255,255,0));
}
std::vector<int> generateRandomLockUnlockSequence(int totalFrames, int minLockDuration, int maxLockDuration)
{
std::vector<int> sequence(totalFrames, 0); // 初始化为全0
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> actionDist(0, 1); // 0:普通帧, 1:锁定
std::uniform_int_distribution<> durationDist(1, 5); // 连续动作的持续时间
std::uniform_int_distribution<> unlockProbDist(0, 100); // 解锁概率分布
std::uniform_int_distribution<> waitFramesDist(1, 3); // 锁定后等待帧数
std::uniform_int_distribution<> waitProbDist(0, 100); // 是否等待的概率分布
int currentFrame = 0;
bool isLocked = false; // 当前是否处于锁定状态
bool justLocked = false; // 是否刚刚执行了锁定操作
while (currentFrame < totalFrames)
{
if (isLocked)
{
// 如果当前是锁定状态有20%的概率解锁
if (unlockProbDist(gen) < 20)
{
sequence[currentFrame] = 2; // 解锁
isLocked = false;
currentFrame++;
continue;
}
}
// 如果刚刚执行了锁定操作有50%的概率添加等待帧
if (justLocked && waitProbDist(gen) < 50)
{
int waitFrames = waitFramesDist(gen);
for (int i = 0; i < waitFrames && currentFrame < totalFrames; i++)
{
sequence[currentFrame] = 0; // 等待帧
currentFrame++;
}
}
justLocked = false;
// 随机决定当前帧的动作类型
int action = actionDist(gen);
// 随机决定这个动作持续多少帧
int duration = durationDist(gen);
// 确保不会超出总帧数
if (currentFrame + duration > totalFrames)
{
duration = totalFrames - currentFrame;
}
// 填充动作序列
for (int i = 0; i < duration && currentFrame < totalFrames; i++)
{
sequence[currentFrame] = action;
if (action == 1)
{
isLocked = true;
justLocked = true; // 标记刚刚执行了锁定操作
}
currentFrame++;
}
}
return sequence;
}

@ -0,0 +1,177 @@
#pragma once
#include <opencv2/opencv.hpp>
#include "NeoArithStandardDll.h"
class SimTargetImage_Y16
{
public:
SimTargetImage_Y16(int w,int h);
~SimTargetImage_Y16();
public:
void setBackGround(int gray,int std);
void addTarget(int x, int y, int w, int h, int gray);
// 获取Y16数据
unsigned short* getImageData();
cv::Mat getMatRGB();
private:
cv::Mat Y8Mat;//显示图像
unsigned short* pSrc;
int nImageWidth;
int nImageHeight;
};
// 目标结构体
struct Target
{
float x, y; // 目标位置
float width, height; // 目标尺寸
float vx, vy; // 水平和垂直速度
float vw, vh; // 尺寸变化速度
cv::Scalar color; // 目标颜色(适用于 RGB
float vc; // 颜色变化率
bool useTexture; // 使用贴图
bool bGrayComplex; //花目标
cv::Scalar color2; //花目标颜色(适用于 RGB
cv::Mat texture_cur; // 贴图
cv::Mat alaph_cur; // 贴图alaph
// 保存原始贴图状态
cv::Mat texture; // 贴图
cv::Mat alaph; // 贴图alaph
Target()
{
useTexture = false;
};
void updatePosition(int frameWidth, int frameHeight)
{
// 更新位置
x += vx;
y += vy;
width += vw;
height += vh;
// 检测边界并反弹
if (x <= width || x + width >= frameWidth) vx = -vx;
if (y <= height || y + height >= frameHeight) vy = -vy;
// 保持目标在图像范围内
x = std::max(0.0f, std::min(x, frameWidth - width));
y = std::max(0.0f, std::min(y, frameHeight - height));
}
void updateTexture()
{
if(useTexture && (texture_cur.cols != height || texture_cur.rows != width))
{
texture_cur = cv::Mat(height,width,CV_8UC3);
alaph_cur = cv::Mat(height,width,CV_8UC1);
cv::resize(texture,texture_cur,cv::Size(width,height));
cv::resize(alaph,alaph_cur,cv::Size(width,height));
}
}
void addTexture(unsigned char* png_data,int Len)
{
std::vector<uchar> img_data(png_data, png_data + Len);
cv::Mat pic = cv::imdecode(img_data, cv::IMREAD_UNCHANGED);
//cv::imshow("pic",pic);
// cv::waitKey(0);
// 分离前景的 RGB 和 Alpha 通道
cv::Mat bgr, alpha;
std::vector<cv::Mat> channels(4);
cv::split(pic, channels);
cv::merge(std::vector<cv::Mat>{channels[0], channels[1], channels[2]}, bgr);
useTexture = true;
alaph = channels[3]; // Alpha 通道
texture = bgr;
alaph_cur = channels[3];
texture_cur = bgr;
}
};
class SimTargetImage
{
public:
SimTargetImage(int w,int h);
~SimTargetImage(){};
public:
// 状态更新
void update();
// 设置背景
void setBackGround(int gray,int std);
// 新增:设置棋盘格背景
void setCheckerboardBackGround(int gray1, int gray2, int blockSize);
// 增加一个目标
void addTarget(Target t);
// 增加一个遮挡
void addOcc(Target t);
public:
cv::Mat getImageRGB();
cv::Mat getImageY16();
cv::Mat getImageY8();
cv::Mat getImageNV12();
Target* getTarget(int id);
private:
void drawObj(Target t);
void drawOcc(Target t);
cv::Mat m_BaseMat;//图像帧(RGB)
cv::Mat m_CurMat;//图像帧(RGB)
std::vector<Target> m_targetList;
std::vector<Target> m_OccList;
int m_imgW;
int m_imgH;
// 各类型输出结果
private:
cv::Mat matY8;
cv::Mat matY16;
cv::Mat matNV12;
};
// 16位调光
void Map16BitTo8Bit(unsigned short* psh16BitData, long lDataLen, unsigned char* pby8BitData);
void showArithInfo(cv::Mat src,ARIDLL_OUTPUT* output);
// 生成随机锁定解锁序列
// 返回值锁定和解锁的帧编号数组1表示锁定2表示解锁0表示普通帧
std::vector<int> generateRandomLockUnlockSequence(int totalFrames, int minLockDuration = 10, int maxLockDuration = 30);

@ -1311,7 +1311,7 @@ SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SI
// 阈值调整
if (pPipe->unLostCnt < 3)
if (pPipe->unLostCnt < 2)
{
fSScaleChangeLowThres = 0.3;
fSScaleChangeHighThres = 3.f;
@ -1328,10 +1328,10 @@ SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SI
fSScaleChangeHighThres = 3.f;
fAScaleChangeLowThres = 0.5;
fAScaleChangeHighThres = 2.0;
nLastDiffThresX = MAX(nMoveMin,12);
nLastDiffThresY = MAX(nMoveMin, 12);
nPredictDiffThresX = MAX(nFThreMin, 12);
nPredictDiffThresY = MAX(nFThreMin, 12);
nLastDiffThresX = MAX(nMoveMin,50);
nLastDiffThresY = MAX(nMoveMin, 50);
nPredictDiffThresX = MAX(nFThreMin, 25);
nPredictDiffThresY = MAX(nFThreMin, 25);
}
else if (pPipe->unLostCnt < 50)
{
@ -1339,8 +1339,8 @@ SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SI
fSScaleChangeHighThres = 5.f;
fAScaleChangeLowThres = 0.33;
fAScaleChangeHighThres = 3.0;
nLastDiffThresX = MAX(nMoveMin, 24);
nLastDiffThresY = MAX(nMoveMin, 24);
nLastDiffThresX = MAX(nMoveMin, 70);
nLastDiffThresY = MAX(nMoveMin, 70);
nPredictDiffThresX = MAX(nFThreMin, 36);
nPredictDiffThresY = MAX(nFThreMin, 36);
}
@ -1350,8 +1350,8 @@ SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SI
fSScaleChangeHighThres = 8.f;
fAScaleChangeLowThres = 0.33;
fAScaleChangeHighThres = 3.0;
nLastDiffThresX = MAX(nMoveMin, 36);
nLastDiffThresY = MAX(nMoveMin, 36);
nLastDiffThresX = MAX(nMoveMin, 120);
nLastDiffThresY = MAX(nMoveMin, 120);
nPredictDiffThresX = MAX(nFThreMin, 48);
nPredictDiffThresY = MAX(nFThreMin, 48);
}
@ -1367,6 +1367,22 @@ SINT32 SA_Tracker::FindMatchTarget(PIPE* pPipe, TARGET_OBJECT* ptTargetArray, SI
nPredictDiffThresY = MAX(nFThreMin, 60);
}
// 小目标特殊处理
if (pPipe->ObjectFilter.fPxlsCnt < 9)
{
fSScaleChangeLowThres = 0.3;
fSScaleChangeHighThres = 3.f;
fAScaleChangeLowThres = 0.5;
fAScaleChangeHighThres = 2.0;
nLastDiffThresX = MAX(nMoveMin, 6);
nLastDiffThresY = MAX(nMoveMin, 6);
nPredictDiffThresX = MAX(nFThreMin, 6);
nPredictDiffThresY = MAX(nFThreMin, 6);
}
SINT32 nEnd = pPipe->ubEnd;
// 尺寸变化强逻辑防跳变// by wcw04046 @ 2020/06/22
if (nSimTargetId != -1 && m_ObjStatus.unContiLostCnt < 200)

@ -21,7 +21,7 @@
// 定义dst最大检测个数
#define DST_MAX_NUM 50
#define DST_MAX_NUM 150
//20170331,雷达导引中心区域恒虚警个数
#define DST_FA_GUIDE_TARGET_NUM 10

@ -3,4 +3,4 @@
#pragma once
#include <string>
std::string BUILD_TIME = "BUILD_TIME @build_time@";
std::string VERSION = "BUILD_VERSION 1.3.2";
std::string VERSION = "BUILD_VERSION 1.3.3";

@ -108,8 +108,8 @@ int main()
char str[100];
sprintf(str,"%d-%d,%d,%d",i,int(stOutput.stTrackers[0].nX - moveX),int(stOutput.stTrackers[0].nY - moveY),stOutput.stTrackers->nPipeLostCnt);
cv::putText(src,cv::String(str),cv::Point(outRect.x - 10,outRect.y),1,2,cv::Scalar(255,255,0));
//imshow("res",src);
//cv::waitKey(2);
imshow("res",src);
cv::waitKey(2);
if ((stOutput.nStatus == GLB_STATUS_TRACK || stOutput.nStatus == GLB_STATUS_MOTRACK) && stOutput.nTrackObjCnts == 1)
{

@ -59,7 +59,7 @@ void QFileList::DisplayFileList(QString path)
foreach(QString str, m_vecFileList)
{
//str.toLower();
QString es = "raw$|xraw$|rawx$|GD$|avi$|mp4$|yuv|MP4|AVI";//by wcw04046
QString es = "raw$|xraw$|rawx$|GD$|avi$|mp4$|yuv|MP4|AVI|data";//by wcw04046
nPos = str.indexOf(QRegExp(es), 0);
if (-1 == nPos)
{

@ -964,10 +964,10 @@ void QVideoPlayer::DrawFrameDetectObjs()
int cx = obj->pfCenPos.x;
int cy = obj->pfCenPos.y;
//int w = MAX(15, obj->snSize.w);
//int h = MAX(15, obj->snSize.h);
int w = obj->snSize.w;
int h = obj->snSize.h;
int w = MAX(10, obj->snSize.w);
int h = MAX(10, obj->snSize.h);
//int w = obj->snSize.w;
//int h = obj->snSize.h;
QRectF bbox(cx - w / 2, cy - h / 2, w, h);
scene->addRect(bbox, QPen(QColor(255, 20, 147), 0.3));

Loading…
Cancel
Save