Files
2026-08-24 10:03:24 +08:00

1302 lines
48 KiB
C++

#define LOG_TAG "detect"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <fstream>
#define USE_DMA_BUFFER
#include <math.h>
#include <float.h>
#include <unistd.h>
using namespace std;
#include "nn_sdk.h"
#include "nn_demo.h"
#include "nn_detect.h"
#include "nn_detect_utils.h"
// for test performance time
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <cutils/log.h>
static struct timeval g_start;
extern "C"
typedef unsigned char uint8_t;
unsigned int g_detect_number = DETECT_NUM;
#define _SET_STATUS_(status, stat, lbl) do {\
status = stat; \
goto lbl; \
}while(0)
#define _CHECK_STATUS_(status, lbl) do {\
if (NULL == status) {\
goto lbl; \
} \
}while(0)
typedef enum {
NETWORK_UNINIT,
NETWORK_INIT,
NETWORK_PREPARING,
NETWORK_PROCESSING,
} network_status;
typedef struct {
dev_type type;
char* value;
char* info;
}chip_info;
typedef void* (*_aml_module_create)(aml_config* config);
typedef int (*_aml_module_input_set)(void* context,nn_input *pInput);
typedef void* (*_aml_module_output_get)(void* context,aml_output_config_t outconfig);
typedef void (*_aml_module_destroy)(void* context);
typedef void (*_aml_util_getHardwareStatus)(int* customID,int *powerStatus,int *ddk_version);
typedef int (*_aml_read_chip_info)(aml_platform_info_t *platform_info);
typedef void* (*_post_process_all_module)(aml_module_t type,nn_output *pOut);
typedef void *(*_aml_util_mallocBuffer)(void* context, aml_memory_config_t* mem_config, aml_memory_data_t* mem_data);
typedef void (*_aml_util_freeBuffer)(void* context, aml_memory_config_t* mem_config, aml_memory_data_t* mem_data);
typedef struct function_process {
_aml_module_create module_create;
_aml_module_input_set module_input_set;
_aml_module_output_get module_output_get;
_aml_module_destroy module_destroy;
_aml_util_getHardwareStatus getHardwareStatus;
_aml_read_chip_info read_chip_info;
_post_process_all_module post_process;
_aml_util_mallocBuffer mallocBuffer;
_aml_util_freeBuffer freeBuffer;
}network_process;
typedef struct detect_network {
det_model_type mtype;
aml_memory_config_t mem_config_in[ADDRESS_MAX_NUM];
aml_memory_data_t memory_data_in[ADDRESS_MAX_NUM];
aml_memory_config_t mem_config_out[ADDRESS_MAX_NUM];
aml_memory_data_t memory_data_out[ADDRESS_MAX_NUM];
network_status status;
void *context;
network_process process;
void * handle_id_user;
void * handle_id_demo;
}det_network_t, *p_det_network_t;
dev_type g_dev_type = DEV_A311D2;
static det_network_t network[DET_BUTT];
const char* data_file_path = "/etc/nn_data"; //need check adla model path on platfrom with AE team
const char * file_name[DET_BUTT]= {
"detect_yolo_v3",
"aml_face_detection",
};
// change to 128 avoid buffer overflow
static char model_path[128];
static const char *coco_names[] = {"person","bicycle","car","motorbike","aeroplane","bus","train",
"truck","boat","traffic light","fire hydrant","stop sign","parking meter",
"bench","bird","cat","dog","horse","sheep","cow","elephant","bear","zebra",
"giraffe","backpack","umbrella","handbag","tie","suitcase","frisbee","skis",
"snowboard","sports ball","kite","baseball bat","baseball glove","skateboard",
"surfboard","tennis racket","bottle","wine glass","cup","fork","knife","spoon",
"bowl","banana","apple","sandwich","orange","broccoli","carrot","hot dog","pizza",
"donut","cake","chair","sofa","pottedplant","bed","diningtable","toilet","tvmonitor",
"laptop","mouse","remote","keyboard","cell phone","microwave","oven","toaster","sink",
"refrigerator","book","clock","vase","scissors","teddy bear","hair drier","toothbrush"};
int get_input_size(det_model_type mtype);
static det_status_t check_input_param(input_image_t imageData, det_model_type modelType)
{
int ret = DET_STATUS_OK;
int size=0,imagesize=0;
if (NULL == imageData.data) {
ALOGE("[%s: %d ] Data buffer is NULL!", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
if (imageData.pixel_format != PIX_FMT_NV21 && imageData.pixel_format != PIX_FMT_RGB888) {
ALOGE("[%s: %d ] Current only support RGB888 and NV21!", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
size = get_input_size(modelType);
if (size == 0) {
ALOGE("[%s: %d ] Get_model_size fail!", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
if (imageData.pixel_format == PIX_FMT_RGB888) {
imagesize = imageData.width*imageData.height*imageData.channel;
if (size != imagesize) {
ALOGE("[%s: %d ] Inputsize not match! model size:%d vs input size:%d\n", __func__, __LINE__, size, imagesize);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
}
exit:
return ret;
}
aml_hw_type_t hw_type = AML_HARDWARE_ADLA;
static void check_and_set_dev_type(det_model_type modelType)
{
unsigned char plat_type;
aml_platform_info_t platform_info;
p_det_network_t net = &network[modelType];
net->process.read_chip_info(&platform_info);
plat_type = platform_info.platform_type;
hw_type = platform_info.hw_type;
if (hw_type == AML_HARDWARE_VSI_UNIFY)
{
int customID,powerStatus,ddk_version;
net->process.getHardwareStatus(&customID,&powerStatus,&ddk_version);
switch (customID)
{
case 125:
ALOGI("[%s: %d ] set_dev_type DEV_REVA and setenv 0", __func__, __LINE__);
g_dev_type = DEV_REVA;
setenv("DEV_TYPE", "0", 0);
break;
case 136:
ALOGI("[%s: %d ] set_dev_type DEV_REVB and setenv 1", __func__, __LINE__);
g_dev_type = DEV_REVB;
setenv("DEV_TYPE", "1", 0);
break;
case 153:
ALOGI("[%s: %d ] set_dev_type DEV_SM1 and setenv 2", __func__, __LINE__);
g_dev_type = DEV_SM1;
setenv("DEV_TYPE", "2", 0);
break;
default:
ALOGE("[%s: %d ] set_dev_type fail, please check the type", __func__, __LINE__);
break;
}
ALOGD("[%s: %d ] customID:%d\n",__func__, __LINE__, customID);
}
else if (hw_type == AML_HARDWARE_ADLA)
{
switch (plat_type)
{
case 0:
ALOGI("[%s: %d ] set_dev_type DEV_C308 and setenv 0", __func__, __LINE__);
g_dev_type = DEV_C308;
setenv("DEV_TYPE", "0", 0);
break;
case 1:
ALOGI("[%s: %d ] set_dev_type DEV_AX201 and setenv 1", __func__, __LINE__);
g_dev_type = DEV_AX201;
setenv("DEV_TYPE", "1", 0);
break;
case 2:
ALOGI("[%s: %d ] set_dev_type DEV_A311D2 and setenv 2", __func__, __LINE__);
g_dev_type = DEV_A311D2;
setenv("DEV_TYPE", "2", 0);
break;
case 3:
ALOGI("[%s: %d ] set_dev_type DEV_T968D4 and setenv 3", __func__, __LINE__);
g_dev_type = DEV_T968D4;
setenv("DEV_TYPE", "3", 0);
break;
case 4:
ALOGI("[%s: %d ] set_dev_type DEV_S905X5 and setenv 4", __func__, __LINE__);
g_dev_type = DEV_S905X5;
setenv("DEV_TYPE", "4", 0);
break;
default:
ALOGE("[%s: %d ] set_dev_type fail, please check the type:%d\n", __func__, __LINE__, plat_type);
break;
}
ALOGD("[%s:%d] Platform_type:%d\n", __func__, __LINE__, plat_type);
}
else
{
ALOGE("[%s: %d ] check_and_set_dev_type fail, please check the hw_type:%d\n", __func__, __LINE__, hw_type);
}
ALOGD("[%s:%d] hw_type:%d\n", __func__, __LINE__, hw_type);
}
extern "C"
void *post_process_all_module(aml_module_t type,nn_output *pOut);
det_status_t check_and_set_function(det_model_type modelType)
{
ALOGI("[%s: %d ] Enter, dlopen so: libnnsdk.so", __func__, __LINE__);
int ret = DET_STATUS_ERROR;
p_det_network_t net = &network[modelType];
net->handle_id_user = dlopen("libnnsdk.so", RTLD_NOW);
if (NULL == net->handle_id_user) {
ALOGE("[%s: %d ] dlopen libnnsdk.so failed!,%s", __func__, __LINE__, dlerror());
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
net->process.module_create = (_aml_module_create)dlsym(net->handle_id_user, "aml_module_create");
_CHECK_STATUS_(net->process.module_create, exit);
net->process.module_input_set = (_aml_module_input_set)dlsym(net->handle_id_user, "aml_module_input_set");
_CHECK_STATUS_(net->process.module_input_set, exit);
net->process.module_output_get = (_aml_module_output_get)dlsym(net->handle_id_user, "aml_module_output_get");
_CHECK_STATUS_(net->process.module_output_get, exit);
net->process.module_destroy = (_aml_module_destroy)dlsym(net->handle_id_user, "aml_module_destroy");
_CHECK_STATUS_(net->process.module_destroy, exit);
net->process.getHardwareStatus = (_aml_util_getHardwareStatus)dlsym(net->handle_id_user, "aml_util_getHardwareStatus");
_CHECK_STATUS_(net->process.getHardwareStatus, exit);
net->process.read_chip_info = (_aml_read_chip_info)dlsym(net->handle_id_user, "aml_read_chip_info");
_CHECK_STATUS_(net->process.read_chip_info, exit);
net->process.mallocBuffer = (_aml_util_mallocBuffer)dlsym(net->handle_id_user, "aml_util_mallocBuffer");
_CHECK_STATUS_(net->process.mallocBuffer, exit);
net->process.freeBuffer = (_aml_util_freeBuffer)dlsym(net->handle_id_user, "aml_util_freeBuffer");
_CHECK_STATUS_(net->process.freeBuffer, exit);
net->process.post_process = (_post_process_all_module)post_process_all_module;
ret = DET_STATUS_OK;
exit:
ALOGI("[%s: %d ] Leave, dlopen so: libnnsdk.so, ret=%d", __func__, __LINE__, ret);
return ret;
}
int get_input_size(det_model_type mtype)
{
int input_size = 0;
switch (mtype)
{
case DET_YOLO_V3:
input_size = 416*416*3;
break;
case DET_AML_FACE_DETECTION:
input_size = 640*384*3;
break;
default:
break;
}
return input_size;
}
det_status_t det_get_model_name(const char * data_file_path, dev_type type,det_model_type mtype)
{
int ret = DET_STATUS_OK;
int index = 0;
switch (mtype)
{
case DET_YOLO_V3:
index = 0;
break;
case DET_AML_FACE_DETECTION:
index = 1;
break;
default:
break;
}
if (hw_type == AML_HARDWARE_VSI_UNIFY)
{
switch (type)
{
case DEV_REVA:
sprintf(model_path, "%s/%s/%s_7d.nb", data_file_path,file_name[index],file_name[index]);
break;
case DEV_REVB:
sprintf(model_path, "%s/%s/%s_88.nb", data_file_path,file_name[index],file_name[index]); // /etc/nn_data/detect_yolo_v3/detect_yolo_v3_88.nb
break;
case DEV_SM1:
sprintf(model_path, "%s/%s/%s_99.nb", data_file_path,file_name[index],file_name[index]);
break;
default:
break;
}
}
else if (hw_type == AML_HARDWARE_ADLA)
{
switch (type) {
case DEV_C308:
sprintf(model_path, "%s/%s/%s_A0001.adla", data_file_path,file_name[index],file_name[index]);
break;
case DEV_AX201:
sprintf(model_path, "%s/%s/%s_A0002.adla", data_file_path,file_name[index],file_name[index]);
break;
case DEV_A311D2:
sprintf(model_path, "%s/%s/%s_A0003.adla", data_file_path, file_name[index],file_name[index]); // /etc/nn_data/detect_yolo_v3/detect_yolo_v3_A0003.adla
break;
case DEV_T968D4:
sprintf(model_path, "%s/%s/%s_A0004.adla", data_file_path, file_name[index],file_name[index]);
break;
case DEV_S905X5:
sprintf(model_path, "%s/%s/%s_A0005.adla", data_file_path, file_name[index],file_name[index]);
break;
default:
break;
}
}
return ret;
}
det_status_t det_set_model(det_model_type modelType)
{
aml_config config;
int ret = DET_STATUS_OK;
int input_size[ADDRESS_MAX_NUM] = {0};
int output_size[ADDRESS_MAX_NUM] = {0};
p_det_network_t net = &network[modelType];
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
if (modelType >= DET_BUTT) {
ALOGE("[%s: %d ] Det_set_model fail, modelType >= BUTT", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
ret = check_and_set_function(modelType);
check_and_set_dev_type(modelType);
if (ret) {
ALOGE("[%s: %d ] ModelType so open failed or Not support now!!", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
memset(&config,0,sizeof(aml_config));
ALOGI("[%s: %d ] Start create Model, data_file_path=%s", __func__, __LINE__, data_file_path);
det_get_model_name(data_file_path,g_dev_type,modelType);
if (hw_type == AML_HARDWARE_VSI_UNIFY)
{
config.nbgType = NN_NBG_FILE;
switch (modelType)
{
case DET_YOLO_V3:
input_size[0] = 416*416*3;
output_size[0] = 13*13*255;
output_size[1] = 26*26*255;
output_size[2] = 52*52*255;
net->mem_config_in[0].cache_type = AML_WITH_CACHE;
net->mem_config_in[0].memory_type = AML_VIRTUAL_ADDR;
net->mem_config_in[0].direction = AML_MEM_DIRECTION_READ_WRITE;
net->mem_config_in[0].index = 0;
net->mem_config_in[0].mem_size = input_size[0];
net->process.mallocBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
config.inOut.inAddr[0] = (uint8_t *)net->memory_data_in[0].viraddr;
for (int i = 0; i < 3; i++)
{
net->mem_config_out[i].cache_type = AML_WITH_CACHE;
net->mem_config_out[i].memory_type = AML_VIRTUAL_ADDR;
net->mem_config_out[i].direction = AML_MEM_DIRECTION_READ_WRITE;
net->mem_config_out[i].index = i;
net->mem_config_out[i].mem_size = output_size[i];
net->process.mallocBuffer(net->context, &net->mem_config_out[i], &net->memory_data_out[i]);
config.inOut.outAddr[i] = (uint8_t *)net->memory_data_out[i].viraddr;
}
config.modelType = DARKNET;
break;
case DET_AML_FACE_DETECTION:
input_size[0] = 640*384*3;
net->mem_config_in[0].cache_type = AML_WITH_CACHE;
net->mem_config_in[0].memory_type = AML_VIRTUAL_ADDR;
net->mem_config_in[0].direction = AML_MEM_DIRECTION_READ_WRITE;
net->mem_config_in[0].index = 0;
net->mem_config_in[0].mem_size = input_size[0];
net->process.mallocBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
config.inOut.inAddr[0] = (uint8_t *)net->memory_data_in[0].viraddr;
config.modelType = TENSORFLOW;
break;
default:
break;
}
}
else if (hw_type == AML_HARDWARE_ADLA)
{
config.nbgType = NN_ADLA_FILE;
config.modelType = ADLA_LOADABLE;
}
ALOGI("[%s: %d ] module_create, model_path=%s", __func__, __LINE__, model_path);
config.path = (const char *)model_path;
config.typeSize = sizeof(aml_config);
net->context = net->process.module_create(&config);
if (net->context == NULL) {
ALOGE("[%s: %d ] Model_create fail, file_path=%s, dev_type=%d", __func__, __LINE__, data_file_path, g_dev_type);
_SET_STATUS_(ret, DET_STATUS_CREATE_NETWORK_FAIL, exit);
}
if (hw_type == AML_HARDWARE_ADLA)//vsi要在模型加载前分配buf,adla要在加载之后分配
{
switch (modelType)
{
case DET_YOLO_V3:
input_size[0] = 416*416*3;
net->mem_config_in[0].cache_type = AML_WITH_CACHE;
net->mem_config_in[0].memory_type = AML_VIRTUAL_ADDR;
net->mem_config_in[0].direction = AML_MEM_DIRECTION_READ_WRITE;
net->mem_config_in[0].index = 0;
net->mem_config_in[0].mem_size = input_size[0];
net->process.mallocBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
break;
case DET_AML_FACE_DETECTION:
input_size[0] = 640*384*3;
net->mem_config_in[0].cache_type = AML_WITH_CACHE;
net->mem_config_in[0].memory_type = AML_VIRTUAL_ADDR;
net->mem_config_in[0].direction = AML_MEM_DIRECTION_READ_WRITE;
net->mem_config_in[0].index = 0;
net->mem_config_in[0].mem_size = input_size[0];
net->process.mallocBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
break;
default:
break;
}
}
net->mtype = modelType;
// LOGI("input_ptr size=%d, addr=%x", input_size[0], net->memory_data_in[0].memory);
net->status = NETWORK_INIT;
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
det_status_t det_get_model_size(det_model_type modelType, int *width, int *height, int *channel)
{
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
if (!net->status) {
ALOGE("[%s: %d ] Model has not created! modeltype:%d", __func__, __LINE__, modelType);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
switch (modelType)
{
case DET_YOLO_V3:
*width = 416;
*height = 416;
*channel = 3;
break;
case DET_AML_FACE_DETECTION:
*width = 640;
*height = 384;
*channel = 3;
break;
default:
break;
}
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
det_status_t det_set_input(input_image_t imageData, det_model_type modelType)
{
nn_input inData;
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
int i,j,tmpdata,nn_width, nn_height, channels,offset;
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
if (!net->status) {
ALOGE("[%s: %d ] Model has not created! modeltype:%d", __func__, __LINE__, modelType);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
gettimeofday(&g_start, NULL);
ret = check_input_param(imageData, modelType);
if (ret) {
ALOGE("[%s: %d ] Check_input_param fail.", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
// need check u8 or i8, prepare diff preprocess
if (hw_type == AML_HARDWARE_VSI_UNIFY)
{
switch (modelType)
{
case DET_YOLO_V3:
det_get_model_size(modelType,&nn_width, &nn_height, &channels);
for (i = 0; i < channels; i++)
{
offset = nn_width * nn_height * i;
for (j = 0; j < nn_width * nn_height; j++)
{
tmpdata = (imageData.data[j * channels + i]);
((unsigned char *)net->memory_data_in[0].viraddr)[j + offset] = tmpdata;
}
}
break;
case DET_AML_FACE_DETECTION:
memcpy(net->memory_data_in[0].viraddr,imageData.data,net->mem_config_in[0].mem_size);
break;
default:
break;
}
inData.input = (uint8_t*)net->memory_data_in[0].viraddr;
}
else if (hw_type == AML_HARDWARE_ADLA)
{
switch (modelType)
{
case DET_YOLO_V3:
case DET_AML_FACE_DETECTION:
memcpy(net->memory_data_in[0].viraddr,imageData.data,net->mem_config_in[0].mem_size);
break;
default:
break;
}
inData.input = (uint8_t*)net->memory_data_in[0].memory;
}
inData.input_type = INPUT_DMA_DATA;
inData.input_index = 0;
inData.size = net->mem_config_in[0].mem_size;
ret = net->process.module_input_set(net->context, &inData);
if (ret)
{
ALOGE("[%s: %d ] Set input fail.", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_SET_INPUT_ERROR, exit);
}
net->status = NETWORK_PREPARING;
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
struct timeval end;
double time_total;
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] det_set_input, time=%lf uS \n", __func__, __LINE__, time_total);
return ret;
}
det_status_t det_set_param(det_model_type modelType, det_param_t param)
{
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
int ret = DET_STATUS_OK;
int number = param.param.det_param.detect_num;
ALOGI("[%s: %d ] detect num is %d\n", __func__, __LINE__, number);
p_det_network_t net = &network[modelType];
if (!net->status) {
ALOGE("[%s: %d ] Model has not created! modeltype:%d", __func__, __LINE__, modelType);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
switch (modelType)
{
case DET_YOLO_V3:
case DET_AML_FACE_DETECTION:
if (number < DETECT_NUM || number > MAX_DETECT_NUM)
{
ret = -1;
}
else
{
g_detect_number = number;
}
ALOGI("[%s: %d ] g_detect_number is %d\n", __func__, __LINE__, g_detect_number);
break;
default:
break;
}
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
det_status_t det_get_param(det_model_type modelType,det_param_t *param)
{
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
if (!net->status) {
ALOGE("[%s: %d ] Model has not created! modeltype:%d", __func__, __LINE__, modelType);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
switch (modelType)
{
case DET_YOLO_V3:
case DET_AML_FACE_DETECTION:
param->param.det_param.detect_num = g_detect_number;
ALOGI("[%s: %d ] g_detect_number is %d\n", __func__, __LINE__, g_detect_number);
break;
default:
break;
}
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
aml_module_t get_sdk_modeltype(det_model_type modelType)
{
aml_module_t type = YOLO_V3;
switch (modelType)
{
case DET_YOLO_V3:
type = YOLO_V3;
break;
case DET_AML_FACE_DETECTION:
type = FACE_LANDMARK_5;
break;
default:
break;
}
return type;
}
void post_process(det_model_type modelType,void* out,pDetResult resultData)
{
ALOGI("[%s: %d ] Enter, post_process modelType:%d", __func__, __LINE__, modelType);
face_landmark5_out_t *face_detect_out = NULL;
yolov3_out_t *yolov3_out = NULL;
float left = 0, right = 0, top = 0, bot=0, prob = 0;
unsigned int i = 0, input_width = 0, input_high = 0;
int label_num = 0;
switch (modelType)
{
case DET_YOLO_V3:
input_width = 416, input_high = 416;
yolov3_out = (yolov3_out_t *)out;
// printf("yolov3_out->detNum = %d\n", yolov3_out->detNum);
resultData->result.det_result.detect_num = yolov3_out->detNum;
resultData->result.det_result.point = (det_position_float_t *)malloc(sizeof(det_position_float_t) * resultData->result.det_result.detect_num);
resultData->result.det_result.result_name = (det_classify_result_t *)malloc(sizeof(det_classify_result_t) * resultData->result.det_result.detect_num);
// printf("detNum = %d\n", yolov3_out->detNum);
for (i=0;i<yolov3_out->detNum;i++)
{
if (i >= g_detect_number) break;
left = (yolov3_out->pBox[i].x-yolov3_out->pBox[i].w/2.)*input_width;
right = (yolov3_out->pBox[i].x+yolov3_out->pBox[i].w/2.)*input_width;
top = (yolov3_out->pBox[i].y-yolov3_out->pBox[i].h/2.)*input_high;
bot = (yolov3_out->pBox[i].y+yolov3_out->pBox[i].h/2.)*input_high;
prob = yolov3_out->pBox[i].score;
label_num = int(yolov3_out->pBox[i].objectClass);
if (left < 2) left = 2;
if (right > input_width-2) right = input_width-2;
if (top < 2) top = 2;
if (bot > input_high-2) bot = input_high-2;
resultData->result.det_result.point[i].type = DET_RECTANGLE_TYPE;
resultData->result.det_result.point[i].point.rectPoint.left = left;
resultData->result.det_result.point[i].point.rectPoint.right = right;
resultData->result.det_result.point[i].point.rectPoint.top = top;
resultData->result.det_result.point[i].point.rectPoint.bottom = bot;
resultData->result.det_result.point[i].point.rectPoint.score = prob;
resultData->result.det_result.result_name[i].label_id = label_num;
memcpy(resultData->result.det_result.result_name[i].label_name, coco_names[label_num], strlen(coco_names[label_num])+1);
ALOGI("[%s: %d ] num:%d, class:%s, label_num:%d, left:%f, right:%f, top:%f, bot:%f, score:%f\n", __func__, __LINE__ ,i+1,
resultData->result.det_result.result_name[i].label_name,
resultData->result.det_result.result_name[i].label_id,
resultData->result.det_result.point[i].point.rectPoint.left,
resultData->result.det_result.point[i].point.rectPoint.right,
resultData->result.det_result.point[i].point.rectPoint.top,
resultData->result.det_result.point[i].point.rectPoint.bottom,
resultData->result.det_result.point[i].point.rectPoint.score);
}
break;
case DET_AML_FACE_DETECTION:
input_width = 640, input_high = 384;
face_detect_out = (face_landmark5_out_t *)out;
resultData->result.det_result.detect_num = face_detect_out->detNum;
resultData->result.det_result.point = (det_position_float_t *)malloc(sizeof(det_position_float_t) * resultData->result.det_result.detect_num);
for (i=0;i<face_detect_out->detNum;i++)
{
if (i >= g_detect_number) break;
left = (face_detect_out->facebox[i].x)*input_width;
right = (face_detect_out->facebox[i].x + face_detect_out->facebox[i].w)*input_width;
top = (face_detect_out->facebox[i].y)*input_high;
bot = (face_detect_out->facebox[i].y + face_detect_out->facebox[i].h)*input_high;
prob = face_detect_out->facebox[i].score;
if (left < 2) left = 2;
if (right > input_width-2) right = input_width-2;
if (top < 2) top = 2;
if (bot > input_high-2) bot = input_high-2;
resultData->result.det_result.point[i].type = DET_RECTANGLE_TYPE;
resultData->result.det_result.point[i].point.rectPoint.left = left;
resultData->result.det_result.point[i].point.rectPoint.right = right;
resultData->result.det_result.point[i].point.rectPoint.top = top;
resultData->result.det_result.point[i].point.rectPoint.bottom = bot;
resultData->result.det_result.point[i].point.rectPoint.score = prob;
resultData->result.det_result.point[i].tpts.floatX[0] = face_detect_out->pos[i][0].x*input_width;
resultData->result.det_result.point[i].tpts.floatY[0] = face_detect_out->pos[i][0].y*input_high;
resultData->result.det_result.point[i].tpts.floatX[1] = face_detect_out->pos[i][1].x*input_width;
resultData->result.det_result.point[i].tpts.floatY[1] = face_detect_out->pos[i][1].y*input_high;
resultData->result.det_result.point[i].tpts.floatX[2] = face_detect_out->pos[i][2].x*input_width;
resultData->result.det_result.point[i].tpts.floatY[2] = face_detect_out->pos[i][2].y*input_high;
resultData->result.det_result.point[i].tpts.floatX[3] = face_detect_out->pos[i][3].x*input_width;
resultData->result.det_result.point[i].tpts.floatY[3] = face_detect_out->pos[i][3].y*input_high;
resultData->result.det_result.point[i].tpts.floatX[4] = face_detect_out->pos[i][4].x*input_width;
resultData->result.det_result.point[i].tpts.floatY[4] = face_detect_out->pos[i][4].y*input_high;
// printf("face_number:%d, left=%f, right=%f, top=%f, bot=%f, score:%f\n", i+1,
// resultData->result.det_result.point[i].point.rectPoint.left,
// resultData->result.det_result.point[i].point.rectPoint.right,
// resultData->result.det_result.point[i].point.rectPoint.top,
// resultData->result.det_result.point[i].point.rectPoint.bottom,
// resultData->result.det_result.point[i].point.rectPoint.score);
// printf("left_eye.x = %f , left_eye.y = %f \n", resultData->result.det_result.point[i].tpts.floatX[0], resultData->result.det_result.point[i].tpts.floatY[0]);
// printf("right_eye.x = %f, right_eye.y = %f \n", resultData->result.det_result.point[i].tpts.floatX[1], resultData->result.det_result.point[i].tpts.floatY[1]);
// printf("nose.x = %f, nose.y = %f \n", resultData->result.det_result.point[i].tpts.floatX[2], resultData->result.det_result.point[i].tpts.floatY[2]);
// printf("left_mouth.x = %f, left_mouth.y = %f \n", resultData->result.det_result.point[i].tpts.floatX[3], resultData->result.det_result.point[i].tpts.floatY[3]);
// printf("right_mouth.x = %f, right_mouth.y = %f\n\n", resultData->result.det_result.point[i].tpts.floatX[4], resultData->result.det_result.point[i].tpts.floatY[4]);
}
break;
default:
break;
}
return;
}
det_status_t det_get_result(pDetResult resultData, det_model_type modelType)
{
aml_output_config_t outconfig;
memset(&outconfig, 0, sizeof(outconfig));
aml_module_t modelType_sdk;
int ret = DET_STATUS_OK;
struct timeval end;
double time_total;
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] det_set_input-det_get_result, time=%lf uS \n", __func__, __LINE__, time_total);
p_det_network_t net = &network[modelType];
void *out;
nn_output *nn_out;
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
if (NETWORK_PREPARING != net->status) {
ALOGE("[%s: %d ] Model not create or not prepared! status=%d", __func__, __LINE__, net->status);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
outconfig.typeSize = sizeof(aml_output_config_t);
modelType_sdk = get_sdk_modeltype(modelType);
if (hw_type == AML_HARDWARE_VSI_UNIFY && modelType == DET_AML_FACE_DETECTION)
{
outconfig.format = AML_OUTDATA_FLOAT32;
}
else
{
outconfig.format = AML_OUTDATA_DMA;
}
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] before AML_PERF_OUTPUT_SET, time=%lf uS \n", __func__, __LINE__, time_total);
outconfig.perfMode = AML_PERF_OUTPUT_SET;
nn_out = (nn_output*)net->process.module_output_get(net->context,outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] AML_PERF_OUTPUT_SET, time=%lf uS \n", __func__, __LINE__, time_total);
outconfig.perfMode = AML_PERF_INFERENCE;
nn_out = (nn_output*)net->process.module_output_get(net->context,outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] AML_PERF_INFERENCE, time=%lf uS \n", __func__, __LINE__, time_total);
outconfig.perfMode = AML_PERF_OUTPUT_GET;
nn_out = (nn_output*)net->process.module_output_get(net->context,outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] AML_PERF_OUTPUT_GET, time=%lf uS \n", __func__, __LINE__, time_total);
out = (void*)net->process.post_process(modelType_sdk, nn_out);
if (out == NULL) {
ALOGE("[%s: %d ] Process Net work fail", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PROCESS_NETWORK_FAIL, exit);
}
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] net->process.post_process, time=%lf uS \n", __func__, __LINE__, time_total);
post_process(modelType,out,resultData);
net->status = NETWORK_PROCESSING;
gettimeofday(&end, NULL);
time_total = (end.tv_sec - g_start.tv_sec)*1000000.0 + (end.tv_usec - g_start.tv_usec);
g_start = end;
ALOGI("[%s: %d ] post_process, time=%lf uS \n", __func__, __LINE__, time_total);
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
det_status_t det_release_model(det_model_type modelType)
{
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
if (!net->status) {
ALOGW("[%s: %d ] Model has benn released!", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_OK, exit);
}
if (hw_type == AML_HARDWARE_VSI_UNIFY)//vsi这边需要对输入输出的DMA buf都进行释放
{
switch (modelType)
{
case DET_YOLO_V3:
if (net->memory_data_in[0].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
if (net->memory_data_out[0].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_out[0], &net->memory_data_out[0]);
if (net->memory_data_out[1].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_out[1], &net->memory_data_out[1]);
if (net->memory_data_out[2].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_out[2], &net->memory_data_out[2]);
break;
case DET_AML_FACE_DETECTION:
if (net->memory_data_in[0].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
break;
default:
break;
}
}
else if (hw_type == AML_HARDWARE_ADLA)//adla只需要释放输入DMA buf
{
switch (modelType)
{
case DET_YOLO_V3:
case DET_AML_FACE_DETECTION:
if (net->memory_data_in[0].viraddr)
net->process.freeBuffer(net->context, &net->mem_config_in[0], &net->memory_data_in[0]);
break;
default:
break;
}
}
if (net->context != NULL) {
net->process.module_destroy(net->context);
net->context = NULL;
}
dlclose(net->handle_id_user);
net->handle_id_user = NULL;
// dlclose(net->handle_id_demo);
// net->handle_id_demo = NULL;
net->status = NETWORK_UNINIT;
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// for async mode, better performance
/////////////////////////////////////////////////////////////////////////////////////////////
// det_status_t det_set_data_to_NPU(input_image_t imageData, det_model_type modelType){
// int ret = DET_STATUS_OK;
// p_det_network_t net = &network[modelType];
// struct timeval start;
// struct timeval end;
// double time_total;
// gettimeofday(&start, NULL);
// int i,j,tmpdata,nn_width, nn_height, channels,offset;
// ret = check_input_param(imageData, modelType);
// if (ret) {
// LOGE("Check_input_param fail.");
// _SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
// }
// if (hw_type == AML_HARDWARE_VSI_UNIFY)
// {
// switch (modelType)
// {
// case DET_YOLO_V3:
// det_get_model_size(modelType,&nn_width, &nn_height, &channels);
// for (i = 0; i < channels; i++)
// {
// offset = nn_width * nn_height * i;
// for (j = 0; j < nn_width * nn_height; j++)
// {
// tmpdata = (imageData.data[j * channels + i]);
// ((unsigned char *)net->memory_data_in[0].viraddr)[j + offset] = tmpdata;
// }
// }
// gettimeofday(&end, NULL);
// time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
// start = end;
// LOGI("det_set_input_to_NPU_u8_change, time=%lf uS \n", time_total);
// break;
// case DET_AML_FACE_DETECTION:
// break;
// default:
// break;
// }
// }
// else if (hw_type == AML_HARDWARE_ADLA)
// {
// switch (modelType)
// {
// case DET_YOLO_V3:
// case DET_AML_FACE_DETECTION:
// memcpy(net->memory_data_in[0].viraddr,imageData.data,net->mem_config_in[0].mem_size);
// break;
// default:
// break;
// }
// }
// return ret;
// exit:
// LOGI("Leave, modeltype:%d", modelType);
// return ret;
// }
static det_status_t det_set_input_to_NPU(input_image_t imageData, det_model_type modelType)
{
nn_input inData;
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
struct timeval start;
struct timeval end;
double time_total;
gettimeofday(&start, NULL);
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
// need check u8 or i8, prepare diff preprocess
//zyadd
int i,j,tmpdata,nn_width, nn_height, channels,offset;
ret = check_input_param(imageData, modelType);
if (ret) {
ALOGE("[%s: %d ] Check_input_param fail.", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PARAM_ERROR, exit);
}
if (hw_type == AML_HARDWARE_VSI_UNIFY)
{
switch (modelType)
{
case DET_YOLO_V3:
det_get_model_size(modelType,&nn_width, &nn_height, &channels);
for (i = 0; i < channels; i++)
{
offset = nn_width * nn_height * i;
for (j = 0; j < nn_width * nn_height; j++)
{
tmpdata = (imageData.data[j * channels + i]);
((unsigned char *)net->memory_data_in[0].viraddr)[j + offset] = tmpdata;
}
}
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] det_set_input_to_NPU_u8_change, time=%lf uS \n", __func__, __LINE__, time_total);
break;
case DET_AML_FACE_DETECTION:
memcpy(net->memory_data_in[0].viraddr,imageData.data,net->mem_config_in[0].mem_size);
break;
default:
break;
}
}
else if (hw_type == AML_HARDWARE_ADLA)
{
switch (modelType)
{
case DET_YOLO_V3:
case DET_AML_FACE_DETECTION:
memcpy(net->memory_data_in[0].viraddr,imageData.data,net->mem_config_in[0].mem_size);
break;
default:
break;
}
//yi.zhang1 add ,for debug dump frame
#if 0
static int currentIndex = 0;
string filename = "output_image_" + std::to_string(currentIndex) + ".raw";
ALOGI("[%s: %d ] we now get the %d frame\n", __func__, __LINE__, currentIndex);
ofstream imageFile(filename, std::ios::binary);
imageFile.write(reinterpret_cast<const char*>(imageData.data), imageData.width * imageData.height * imageData.channel);
imageFile.close();
currentIndex++;
#endif
}
inData.input_type = INPUT_DMA_DATA;
inData.input_index = 0;
inData.size = net->mem_config_in[0].mem_size;
inData.input = (uint8_t*)net->memory_data_in[0].memory;
ret = net->process.module_input_set(net->context, &inData);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] net->process.module_input_set, time=%lf uS \n", __func__, __LINE__, time_total);
if (ret)
{
ALOGE("[%s: %d ] Set input fail.", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_SET_INPUT_ERROR, exit);
}
net->status = NETWORK_PREPARING;
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
static det_status_t det_get_outconfig(det_model_type modelType, aml_output_config_t *pOutconfig)
{
int ret = DET_STATUS_OK;
pOutconfig->typeSize = sizeof(aml_output_config_t);
// pOutconfig->format = AML_OUTDATA_DMA;
if (hw_type == AML_HARDWARE_VSI_UNIFY && modelType == DET_AML_FACE_DETECTION)
{
pOutconfig->format = AML_OUTDATA_FLOAT32;
}
else
{
pOutconfig->format = AML_OUTDATA_DMA;
}
return ret;
}
static det_status_t det_set_output_to_NPU(det_model_type modelType, aml_output_config_t *pOutconfig)
{
int ret = DET_STATUS_OK;
p_det_network_t net = &network[modelType];
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
if (NETWORK_PREPARING != net->status) {
ALOGE("[%s: %d ] Model not create or not prepared! status=%d", __func__, __LINE__, net->status);
_SET_STATUS_(ret, DET_STATUS_ERROR, exit);
}
pOutconfig->perfMode = AML_PERF_OUTPUT_SET;
net->process.module_output_get(net->context, *pOutconfig);
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
//nn_output *nn_out = NULL;
// trigger NPU HW thread will call this function
det_status_t det_trigger_inference(input_image_t imageData, det_model_type modelType)
{
aml_output_config_t outconfig;
memset(&outconfig, 0, sizeof(outconfig));
p_det_network_t net = &network[modelType];
int ret = DET_STATUS_OK;
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
struct timeval start;
struct timeval end;
double time_total;
gettimeofday(&start, NULL);
/////////////////////////////////////////////////////////////////////////////////
// 1. set input
det_set_input_to_NPU(imageData, modelType);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] det_set_input_to_NPU, time=%lf uS \n", __func__, __LINE__, time_total);
/////////////////////////////////////////////////////////////////////////////////
// get outconfig
det_get_outconfig(modelType, &outconfig);
// 2. set output
det_set_output_to_NPU(modelType, &outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] det_set_output_to_NPU, time=%lf uS \n", __func__, __LINE__, time_total);
/////////////////////////////////////////////////////////////////////////////////
// set triggler inference
outconfig.perfMode = AML_PERF_INFERENCE;
net->process.module_output_get(net->context, outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] AML_PERF_INFERENCE, time=%lf uS \n", __func__, __LINE__, time_total);
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}
// analysis output, and notify next pipe , result thread will call this function
det_status_t det_get_inference_result(pDetResult resultData, det_model_type modelType)
{
aml_output_config_t outconfig;
memset(&outconfig, 0, sizeof(outconfig));
p_det_network_t net = &network[modelType];
int ret = DET_STATUS_OK;
nn_output *nn_out;
void *out;
ALOGI("[%s: %d ] Enter, modeltype:%d", __func__, __LINE__, modelType);
struct timeval start;
struct timeval end;
double time_total;
gettimeofday(&start, NULL);
// get outconfig
det_get_outconfig(modelType, &outconfig);
outconfig.perfMode = AML_PERF_OUTPUT_GET;
nn_out = (nn_output*)net->process.module_output_get(net->context, outconfig);
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] AML_PERF_OUTPUT_GET, num=%d, out[0]=%d, out[1]=%d, out[2]=%d, time=%lf uS\n", __func__, __LINE__, nn_out->num, nn_out->out[0].size, nn_out->out[1].size, nn_out->out[2].size, time_total);
aml_module_t modelType_sdk;
modelType_sdk = get_sdk_modeltype(modelType);
out = (void*)net->process.post_process(modelType_sdk, nn_out);
if (out == NULL) {
ALOGE("[%s: %d ] Process Net work fail", __func__, __LINE__);
_SET_STATUS_(ret, DET_STATUS_PROCESS_NETWORK_FAIL, exit);
}
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] nnsdk, time=%lf uS \n", __func__, __LINE__, time_total);
post_process(modelType, out, resultData);
net->status = NETWORK_PROCESSING;
gettimeofday(&end, NULL);
time_total = (end.tv_sec - start.tv_sec)*1000000.0 + (end.tv_usec - start.tv_usec);
start = end;
ALOGI("[%s: %d ] post_process, time=%lf uS \n", __func__, __LINE__, time_total);
exit:
ALOGI("[%s: %d ] Leave, modeltype:%d", __func__, __LINE__, modelType);
return ret;
}