调整目录结构,改为一个模型一个文件夹,Makefile文件增加log日志打印等级
This commit is contained in:
parent
17c17af53f
commit
8b7b08a54b
|
@ -2,9 +2,5 @@
|
|||
/docs/
|
||||
.vscode/
|
||||
*.o
|
||||
yolov8s
|
||||
yolov5s
|
||||
Makefile
|
||||
Makefile-bak
|
||||
Doxyfile
|
||||
libpnna.a
|
|
@ -0,0 +1,49 @@
|
|||
EXEC = resnet18
|
||||
OBJDIR = ./obj
|
||||
TOOLCHAIN_DIR = /home/xyy/gcc-arm-8.3
|
||||
SDK_DIR = /home/xyy/m6678e/driver
|
||||
PNNA_DIR = ../../pnna_driver
|
||||
JPEG_DIR = ../../3rdparty
|
||||
|
||||
CC = $(TOOLCHAIN_DIR)/bin/arm-linux-gnueabihf-gcc
|
||||
|
||||
INCLUDES = -I$(PNNA_DIR)/include -I$(JPEG_DIR)
|
||||
CFLAGS = -Wall -fPIC $(INCLUDES) -DNDEBUG -DLOGLEVEL=2
|
||||
LIBS = -lm -L$(SDK_DIR)/lib -lPNNAlite -lPNNAuser
|
||||
|
||||
SRC_MAIN = resnet18_demo.c postprocess/classification_post.c
|
||||
|
||||
PNNA_SRC = $(PNNA_DIR)/src/nn_api.c \
|
||||
$(PNNA_DIR)/src/nn_utils.c \
|
||||
$(PNNA_DIR)/src/preprocess.c \
|
||||
$(PNNA_DIR)/src/quantize.c \
|
||||
$(PNNA_DIR)/src/normalize.c
|
||||
|
||||
OBJ_MAIN = $(patsubst %.c, $(OBJDIR)/%.o, $(SRC_MAIN))
|
||||
OBJ_PNNA = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(PNNA_SRC)))
|
||||
OBJ = $(OBJ_MAIN) $(OBJ_PNNA)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OBJDIR) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: postprocess/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: ../../pnna_driver/src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(EXEC)
|
|
@ -0,0 +1,49 @@
|
|||
EXEC = yolov4_tiny
|
||||
OBJDIR = ./obj
|
||||
TOOLCHAIN_DIR = /home/xyy/gcc-arm-8.3
|
||||
SDK_DIR = /home/xyy/m6678e/driver
|
||||
PNNA_DIR = ../../pnna_driver
|
||||
JPEG_DIR = ../../3rdparty
|
||||
|
||||
CC = $(TOOLCHAIN_DIR)/bin/arm-linux-gnueabihf-gcc
|
||||
|
||||
INCLUDES = -I$(PNNA_DIR)/include -I$(JPEG_DIR)
|
||||
CFLAGS = -Wall -fPIC $(INCLUDES) -DNDEBUG -DLOGLEVEL=2
|
||||
LIBS = -lm -L$(SDK_DIR)/lib -lPNNAlite -lPNNAuser
|
||||
|
||||
SRC_MAIN = yolov4_tiny_demo.c postprocess/yolov4_tiny_post.c
|
||||
|
||||
PNNA_SRC = $(PNNA_DIR)/src/nn_api.c \
|
||||
$(PNNA_DIR)/src/nn_utils.c \
|
||||
$(PNNA_DIR)/src/preprocess.c \
|
||||
$(PNNA_DIR)/src/quantize.c \
|
||||
$(PNNA_DIR)/src/normalize.c
|
||||
|
||||
OBJ_MAIN = $(patsubst %.c, $(OBJDIR)/%.o, $(SRC_MAIN))
|
||||
OBJ_PNNA = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(PNNA_SRC)))
|
||||
OBJ = $(OBJ_MAIN) $(OBJ_PNNA)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OBJDIR) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: postprocess/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: ../../pnna_driver/src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(EXEC)
|
|
@ -0,0 +1,49 @@
|
|||
EXEC = yolov5s
|
||||
OBJDIR = ./obj
|
||||
TOOLCHAIN_DIR = /home/xyy/gcc-arm-8.3
|
||||
SDK_DIR = /home/xyy/m6678e/driver
|
||||
PNNA_DIR = ../../pnna_driver
|
||||
JPEG_DIR = ../../3rdparty
|
||||
|
||||
CC = $(TOOLCHAIN_DIR)/bin/arm-linux-gnueabihf-gcc
|
||||
|
||||
INCLUDES = -I$(PNNA_DIR)/include -I$(JPEG_DIR)
|
||||
CFLAGS = -Wall -fPIC $(INCLUDES) -DNDEBUG -DLOGLEVEL=2
|
||||
LIBS = -lm -L$(SDK_DIR)/lib -lPNNAlite -lPNNAuser
|
||||
|
||||
SRC_MAIN = yolov5s_demo.c postprocess/yolov5s_post.c
|
||||
|
||||
PNNA_SRC = $(PNNA_DIR)/src/nn_api.c \
|
||||
$(PNNA_DIR)/src/nn_utils.c \
|
||||
$(PNNA_DIR)/src/preprocess.c \
|
||||
$(PNNA_DIR)/src/quantize.c \
|
||||
$(PNNA_DIR)/src/normalize.c
|
||||
|
||||
OBJ_MAIN = $(patsubst %.c, $(OBJDIR)/%.o, $(SRC_MAIN))
|
||||
OBJ_PNNA = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(PNNA_SRC)))
|
||||
OBJ = $(OBJ_MAIN) $(OBJ_PNNA)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OBJDIR) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: postprocess/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: ../../pnna_driver/src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(EXEC)
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* @Author: lixiao zhaoyue
|
||||
* @Date: 2024-09-03 16:02:39
|
||||
* @LastEditors: xun
|
||||
* @LastEditTime: 2025-05-21 10:58:47
|
||||
* @Description:
|
||||
* Copyright (c) 2024 by CCYH, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "yolov5s_post.h"
|
||||
#include "preprocess.h"
|
||||
#include "log.h"
|
||||
|
||||
#define MAX_DET_NUM 100
|
||||
|
||||
/**
|
||||
* 比较函数,用于按得分降序排序
|
||||
*/
|
||||
int compare(const void *pa, const void *pb)
|
||||
{
|
||||
const detection *a = (const detection *)pa;
|
||||
const detection *b = (const detection *)pb;
|
||||
return a->scores < b->scores ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算两个检测框的交并比 (IoU)
|
||||
*/
|
||||
float iou(detection a, detection b)
|
||||
{
|
||||
float x1 = (a.boxes.x > b.boxes.x) ? a.boxes.x : b.boxes.x;
|
||||
float y1 = (a.boxes.y > b.boxes.y) ? a.boxes.y : b.boxes.y;
|
||||
float x2 = (a.boxes.w < b.boxes.w) ? a.boxes.w : b.boxes.w;
|
||||
float y2 = (a.boxes.h < b.boxes.h) ? a.boxes.h : b.boxes.h;
|
||||
|
||||
if (x2 < x1 || y2 < y1) return 0;
|
||||
|
||||
float inter_area = (x2 - x1) * (y2 - y1);
|
||||
float a_area = (a.boxes.w - a.boxes.x) * (a.boxes.h - a.boxes.y);
|
||||
float b_area = (b.boxes.w - b.boxes.x) * (b.boxes.h - b.boxes.y);
|
||||
|
||||
return inter_area / (a_area + b_area - inter_area);
|
||||
}
|
||||
|
||||
/**
|
||||
* 非极大值抑制 (NMS)
|
||||
*/
|
||||
void nms(detection *object, detection *result, uint16_t *total, float nmsThreshold)
|
||||
{
|
||||
qsort(object, *total, sizeof(detection), compare);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
uint16_t valid_count = 0;
|
||||
for (i = 0; i < *total; ++i) {
|
||||
int keep = 1;
|
||||
for (j = 0; j < valid_count; ++j) {
|
||||
if (iou(result[j], object[i]) > nmsThreshold) {
|
||||
keep = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keep) {
|
||||
result[valid_count++] = object[i];
|
||||
}
|
||||
}
|
||||
*total = valid_count;
|
||||
}
|
||||
|
||||
int yolov5s_postprocess(void *output, nn_tensor *input, void *none, int counts)
|
||||
{
|
||||
if (!output || !input || (counts <= 0)) {
|
||||
log_error("Invalid input parameters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i = 0, j = 0, c = 0, num = 0;
|
||||
unsigned int x_dims[3] = {1, 25200, 85};
|
||||
detection *dets = (detection *)output;
|
||||
|
||||
unsigned int *index = (unsigned int *)malloc(x_dims[1] * sizeof(unsigned int));
|
||||
if (NULL == index) {
|
||||
log_error("Memory allocation failed for index\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
detection *det_before = (detection *)malloc(MAX_DET_NUM * sizeof(detection));
|
||||
if (det_before == NULL) {
|
||||
log_error("Memory allocation failed for det_before.\n");
|
||||
free(index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (c = 0; c < counts; c++) {
|
||||
float *in_buff = (float *)input[c]->buffer.data;
|
||||
if (in_buff == NULL) {
|
||||
log_error("Invalid input tensor\n");
|
||||
return NN_ERROR_POSTPROCESS;
|
||||
}
|
||||
|
||||
for (i = 0; i < x_dims[1]; i++) {
|
||||
int pos_of_obj_id = 4 + i * x_dims[2];
|
||||
if (in_buff[pos_of_obj_id] > CONFIDENCE_THRESHOLD) {
|
||||
index[num++] = i;
|
||||
}
|
||||
if (num > MAX_DET_NUM) break;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
unsigned int idx = index[i];
|
||||
float *data = &in_buff[idx * x_dims[2]];
|
||||
|
||||
float x_center = data[0];
|
||||
float y_center = data[1];
|
||||
float width = data[2];
|
||||
float height = data[3];
|
||||
float score = data[4];
|
||||
|
||||
det_before[i].boxes.x = x_center - width / 2;
|
||||
det_before[i].boxes.y = y_center - height / 2;
|
||||
det_before[i].boxes.w = x_center + width / 2;
|
||||
det_before[i].boxes.h = y_center + height / 2;
|
||||
det_before[i].scores = score;
|
||||
|
||||
float max_score = 0.0f;
|
||||
int max_class_id = -1;
|
||||
for (j = 5; j < x_dims[2]; j++) {
|
||||
if (data[j] > max_score) {
|
||||
max_score = data[j];
|
||||
max_class_id = j - 5;
|
||||
}
|
||||
}
|
||||
det_before[i].classes = max_class_id;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t total = num;
|
||||
nms(det_before, dets, &total, IOU_THRESHOLD);
|
||||
|
||||
for (i = 0; i < total; i++) {
|
||||
dets[i].total_num = total;
|
||||
}
|
||||
|
||||
free(index);
|
||||
free(det_before);
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* YOLOv5 后处理
|
||||
*/
|
||||
int yolov5s_postprocess_dq(void *output, nn_tensor *input, void *quant_params, int counts)
|
||||
{
|
||||
if (!output || !input || !quant_params || (counts <= 0)) {
|
||||
log_error("Invalid input parameters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
pnna_buffer_create_params_t *qp = (pnna_buffer_create_params_t *)quant_params;
|
||||
nn_tensor *quant_buff = (nn_tensor *)malloc(counts * sizeof(nn_tensor));
|
||||
if (NULL == quant_buff) {
|
||||
log_error("malloc quant_buff failed\n");
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < counts; i++) {
|
||||
quant_buff[i] = create_tensor(DT_FLOAT32, qp[i].sizes, qp[i].num_of_dims);
|
||||
if (NULL == quant_buff[i]) {
|
||||
log_error("create_tensor quant_buff[%d] failed\n", i);
|
||||
destroy_tensor_array(quant_buff, counts);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
status = nn_dequantize_vector(quant_buff, input, qp, counts);
|
||||
if (status < 0) {
|
||||
log_error("dequantize failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = yolov5s_postprocess(output, quant_buff, NULL, counts);
|
||||
|
||||
log_debug("[destroy_tensor] quant_buff address: %p\n", quant_buff);
|
||||
destroy_tensor_array(quant_buff, counts);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int print_yolov5s_result(void *results, unsigned short nboxes)
|
||||
{
|
||||
if (NULL == results) {
|
||||
log_error("Invalid input parameters\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int status = 0;
|
||||
detection *dets =(detection *)results;
|
||||
|
||||
printf("Total detections: %d\n", nboxes);
|
||||
for (i = 0; i < nboxes; i++) {
|
||||
printf("Scores: %.2f, Boxes: [%.2f, %.2f, %.2f, %.2f], Class ID: %d\n",
|
||||
dets[i].scores,
|
||||
dets[i].boxes.x,
|
||||
dets[i].boxes.y,
|
||||
dets[i].boxes.w,
|
||||
dets[i].boxes.h,
|
||||
dets[i].classes);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* @file yolov5s_post.h
|
||||
* @author @zhaoyue (zhaoyue@hngwg.com) @lx(CMEM)
|
||||
* @brief 神经网络模型 yolov5s 的后处理相关函数
|
||||
* @version 2.0
|
||||
* @date 2025-05-22 16:34
|
||||
*
|
||||
* Copyright (c) 2025 by CCYH, All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
#ifndef _YOLOV5S_POST_H_
|
||||
#define _YOLOV5S_POST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nn_api.h"
|
||||
|
||||
#define CONFIDENCE_THRESHOLD 0.45f
|
||||
#define IOU_THRESHOLD 0.25f
|
||||
|
||||
typedef struct _box {
|
||||
float x, y, w, h;
|
||||
} box;
|
||||
|
||||
typedef struct _detection
|
||||
{
|
||||
box boxes;
|
||||
float scores;
|
||||
int classes;
|
||||
int total_num;
|
||||
} detection;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 执行带反量化处理的YOLOv5后处理函数。
|
||||
*
|
||||
* 先通过量化参数创建反量化缓冲区,将量化后的输入tensor反量化为浮点数据,再调用标准后处理流程
|
||||
*
|
||||
* @param output [OUT] 检测结果数组,存储处理后的目标信息
|
||||
* @param input [IN] 量化后的模型输出tensor数组
|
||||
* @param quant_params [IN] 量化参数指针,包含反量化参数信息
|
||||
* @param counts [IN] 模型输出的层数,即输入tensor数组的个数
|
||||
* @return int 成功时返回检测到的目标数量(>=0),若出现错误(如内存分配失败、反量化失败等)返回-1
|
||||
*/
|
||||
int yolov5s_postprocess_dq(void *output, nn_tensor *input, void *quant_params, int counts);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 进行YOLO后处理的函数,将模型输出的tensor数据转换为检测结果数组。
|
||||
*
|
||||
* 处理包括置信度阈值筛选、边界框转换、类别分数计算及非极大值抑制(NMS)
|
||||
*
|
||||
* @param output [OUT] 检测结果数组,存储处理后的目标信息
|
||||
* @param input [IN] 模型输出的tensor数组,每个元素对应一个输出层
|
||||
* @param none [IN] 未使用的保留参数
|
||||
* @param counts [IN] 模型输出的层数,即输入tensor数组的个数
|
||||
* @return int 成功时返回检测到的目标数量(>=0),其他表示失败
|
||||
*/
|
||||
int yolov5s_postprocess(void *output, nn_tensor *input, void *none, int counts);
|
||||
|
||||
/**
|
||||
* @brief 打印yolov5s后处理结果
|
||||
*
|
||||
* @param results [IN] 结果地址
|
||||
* @param nboxes [IN] 目标个数
|
||||
* @return int 返回处理后的状态码,0表示成功,-1表示失败
|
||||
*/
|
||||
int print_yolov5s_result(void *results, unsigned short nboxes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !_YOLOV5S_POST_H_
|
Binary file not shown.
After Width: | Height: | Size: 220 KiB |
Binary file not shown.
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @file yolov5s_demo.c
|
||||
* @author @xun (xunyingya@hngwg.com)
|
||||
* @brief yolov5s 示例工程
|
||||
* @version 2.0
|
||||
* @date 2025-05-23 14:37
|
||||
*
|
||||
* Copyright (c) 2025 by CCYH, All Rights Reserved.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "nn_api.h"
|
||||
#include "nn_utils.h"
|
||||
#include "preprocess.h"
|
||||
#include "postprocess/yolov5s_post.h"
|
||||
|
||||
#ifdef _TMS320C6X
|
||||
#include <c6x.h>
|
||||
#include "M6678E_PLL.h"
|
||||
#include "M6678E_PSC.h"
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t loop_count = 1;
|
||||
detection *dets = (detection *)malloc(10 * sizeof(detection));
|
||||
if (NULL == dets) {
|
||||
printf("Malloc detection failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open Pnna Device
|
||||
status = pnna_open();
|
||||
if (status != NN_SUCCESS) {
|
||||
printf("Open Pnna device failed.\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifdef __linux
|
||||
const char *image_filename = "car.jpg"; // car_int16.dat car.jpg
|
||||
const char *nbg_filename = "yolov5s-int16.nb";
|
||||
|
||||
normalization_params_t norm_params = {
|
||||
.mean = { 0, 0, 0 },
|
||||
.scale = 1.0f / 255.0f
|
||||
};
|
||||
|
||||
buffer_t *nbg_buffer = read_nbg(nbg_filename);
|
||||
if (NULL == nbg_buffer) {
|
||||
printf("Read NBG failed.\n");
|
||||
goto exit;
|
||||
}
|
||||
log_debug("Load NBG data OK ✅...\n");
|
||||
|
||||
// app_ctx_t *yolov5s_model = create_app_ctx(&nbg_buffer,
|
||||
// NULL,
|
||||
// NULL,
|
||||
// yolov5s_postprocess_dq);
|
||||
|
||||
app_ctx_t *yolov5s_model = create_app_ctx(nbg_buffer,
|
||||
&norm_params,
|
||||
preprocess_normalize_quantize,
|
||||
yolov5s_postprocess_dq);
|
||||
|
||||
if (NULL == yolov5s_model) {
|
||||
printf("Create app_ctx_t failed.\n");
|
||||
goto exit;
|
||||
}
|
||||
printf("create_app_ctx done\n");
|
||||
|
||||
while (loop_count > 0)
|
||||
{
|
||||
nn_tensor input_data = load_image(image_filename);
|
||||
|
||||
if (NULL == input_data) {
|
||||
destroy_tensor(input_data);
|
||||
break;
|
||||
}
|
||||
app(yolov5s_model, (void **)&dets, &input_data);
|
||||
print_yolov5s_result(dets, dets[0].total_num);
|
||||
|
||||
destroy_tensor(input_data);
|
||||
loop_count--;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _TMS320C6X
|
||||
network_address = (uint32_t *)0xE0000000;
|
||||
input_dat0_address = (uint32_t *)0xE1000000;
|
||||
my_network_size = 22097124;
|
||||
my_input_size = 2457600;
|
||||
buffer nbg_buffer = {
|
||||
.data = (void *)network_address,
|
||||
.size = my_network_size
|
||||
};
|
||||
|
||||
buffer input_data = {
|
||||
.data = (void *)input_dat0_address,
|
||||
.size = my_input_size
|
||||
};
|
||||
|
||||
app_ctx_t *yolov5s_model = create_app_ctx(&nbg_buffer,
|
||||
NULL,
|
||||
NULL,
|
||||
yolov5s_postprocess_dq);
|
||||
|
||||
if (NULL == yolov5s_model) {
|
||||
printf("Create app_ctx_t failed.\n");
|
||||
goto exit;
|
||||
}
|
||||
printf("create_app_ctx done\n");
|
||||
|
||||
while (loop_count > 0)
|
||||
{
|
||||
app(yolov5s_model, dets, &input_data);
|
||||
loop_count--;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
#ifdef __linux__
|
||||
free_nbg_buffer(nbg_buffer);
|
||||
#endif
|
||||
free(dets);
|
||||
destroy_app_ctx(yolov5s_model);
|
||||
printf("destroy app_ctx_t done.\n");
|
||||
pnna_close();
|
||||
printf("pnna closed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
EXEC = yolov5s_relu
|
||||
OBJDIR = ./obj
|
||||
TOOLCHAIN_DIR = /home/xyy/gcc-arm-8.3
|
||||
SDK_DIR = /home/xyy/m6678e/driver
|
||||
PNNA_DIR = ../../pnna_driver
|
||||
JPEG_DIR = ../../3rdparty
|
||||
|
||||
CC = $(TOOLCHAIN_DIR)/bin/arm-linux-gnueabihf-gcc
|
||||
|
||||
INCLUDES = -I$(PNNA_DIR)/include -I$(JPEG_DIR)
|
||||
CFLAGS = -Wall -fPIC $(INCLUDES) -DNDEBUG -DLOGLEVEL=2
|
||||
LIBS = -lm -L$(SDK_DIR)/lib -lPNNAlite -lPNNAuser
|
||||
|
||||
SRC_MAIN = yolov5s_relu_demo.c postprocess/yolov5s_relu_post.c
|
||||
|
||||
PNNA_SRC = $(PNNA_DIR)/src/nn_api.c \
|
||||
$(PNNA_DIR)/src/nn_utils.c \
|
||||
$(PNNA_DIR)/src/preprocess.c \
|
||||
$(PNNA_DIR)/src/quantize.c \
|
||||
$(PNNA_DIR)/src/normalize.c
|
||||
|
||||
OBJ_MAIN = $(patsubst %.c, $(OBJDIR)/%.o, $(SRC_MAIN))
|
||||
OBJ_PNNA = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(PNNA_SRC)))
|
||||
OBJ = $(OBJ_MAIN) $(OBJ_PNNA)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OBJDIR) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: postprocess/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: ../../pnna_driver/src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(EXEC)
|
|
@ -0,0 +1,49 @@
|
|||
EXEC = yolov8s
|
||||
OBJDIR = ./obj
|
||||
TOOLCHAIN_DIR = /home/xyy/gcc-arm-8.3
|
||||
SDK_DIR = /home/xyy/m6678e/driver
|
||||
PNNA_DIR = ../../pnna_driver
|
||||
JPEG_DIR = ../../3rdparty
|
||||
|
||||
CC = $(TOOLCHAIN_DIR)/bin/arm-linux-gnueabihf-gcc
|
||||
|
||||
INCLUDES = -I$(PNNA_DIR)/include -I$(JPEG_DIR)
|
||||
CFLAGS = -Wall -fPIC $(INCLUDES) -DNDEBUG -DLOGLEVEL=2
|
||||
LIBS = -lm -L$(SDK_DIR)/lib -lPNNAlite -lPNNAuser
|
||||
|
||||
SRC_MAIN = yolov8s_demo.c postprocess/yolov8s_post.c
|
||||
|
||||
PNNA_SRC = $(PNNA_DIR)/src/nn_api.c \
|
||||
$(PNNA_DIR)/src/nn_utils.c \
|
||||
$(PNNA_DIR)/src/preprocess.c \
|
||||
$(PNNA_DIR)/src/quantize.c \
|
||||
$(PNNA_DIR)/src/normalize.c
|
||||
|
||||
OBJ_MAIN = $(patsubst %.c, $(OBJDIR)/%.o, $(SRC_MAIN))
|
||||
OBJ_PNNA = $(patsubst %.c, $(OBJDIR)/%.o, $(notdir $(PNNA_SRC)))
|
||||
OBJ = $(OBJ_MAIN) $(OBJ_PNNA)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OBJDIR) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(LIBS) -o $@
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir -p $(OBJDIR)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: postprocess/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/%.o: ../../pnna_driver/src/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) $(EXEC)
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* @Author: xun
|
||||
* @Date: 2025-02-14 10:22:55
|
||||
* @LastEditors: xun
|
||||
* @LastEditTime: 2025-03-05 13:50:49
|
||||
* @Description:
|
||||
* Copyright (c) 2025 by CCYH, All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "yolov8s_post.h"
|
||||
#include "log.h"
|
||||
|
||||
#define CONFIDENCE_THRESHOLD 0.45f
|
||||
#define IOU_THRESHOLD 0.25f
|
||||
#define GRID_ROW_COUNT 8400
|
||||
#define NUM_CLASSES 80
|
||||
|
||||
int compare(const void *a, const void *b)
|
||||
{
|
||||
detection *det_a = (detection *)a;
|
||||
detection *det_b = (detection *)b;
|
||||
return (det_a->scores < det_b->scores) ? 1 : -1;
|
||||
}
|
||||
|
||||
float iou(detection a, detection b)
|
||||
{
|
||||
float x1 = (a.boxes.x > b.boxes.x) ? a.boxes.x : b.boxes.x;
|
||||
float y1 = (a.boxes.y > b.boxes.y) ? a.boxes.y : b.boxes.y;
|
||||
float x2 = (a.boxes.w < b.boxes.w) ? a.boxes.w : b.boxes.w;
|
||||
float y2 = (a.boxes.h < b.boxes.h) ? a.boxes.h : b.boxes.h;
|
||||
|
||||
if (x2 < x1 || y2 < y1) return 0;
|
||||
|
||||
float inter_area = (x2 - x1) * (y2 - y1);
|
||||
float a_area = (a.boxes.w - a.boxes.x) * (a.boxes.h - a.boxes.y);
|
||||
float b_area = (b.boxes.w - b.boxes.x) * (b.boxes.h - b.boxes.y);
|
||||
|
||||
return inter_area / (a_area + b_area - inter_area);
|
||||
}
|
||||
|
||||
void nms(detection *object, detection *result, uint16_t *total, float nmsThreshold)
|
||||
{
|
||||
qsort(object, *total, sizeof(detection), compare);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
uint16_t valid_count = 0;
|
||||
for (i = 0; i < *total; ++i) {
|
||||
int keep = 1;
|
||||
for (j = 0; j < valid_count; ++j) {
|
||||
if (iou(result[j], object[i]) > nmsThreshold) {
|
||||
keep = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (keep) {
|
||||
result[valid_count++] = object[i];
|
||||
}
|
||||
}
|
||||
*total = valid_count;
|
||||
}
|
||||
|
||||
int yolov8s_postprocess(detection *dets, void **input_buffer, int counts)
|
||||
{
|
||||
if (!dets || !input_buffer || (counts <= 0)) {
|
||||
log_error("Invalid input parameters\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0, j = 0;
|
||||
detection det_before[MAX_DET_NUM];
|
||||
uint16_t valid_count = 0;
|
||||
|
||||
float *input_coords = (float *)input_buffer[0];
|
||||
float *input_scores = (float *)input_buffer[1];
|
||||
|
||||
if ((NULL == input_coords) || (NULL == input_scores)) {
|
||||
log_error("Invalid input buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t offset_x = 0 * GRID_ROW_COUNT;
|
||||
uint16_t offset_y = 1 * GRID_ROW_COUNT;
|
||||
uint16_t offset_w = 2 * GRID_ROW_COUNT;
|
||||
uint16_t offset_h = 3 * GRID_ROW_COUNT;
|
||||
|
||||
for (i = 0; i < GRID_ROW_COUNT; i++)
|
||||
{
|
||||
if (valid_count >= MAX_DET_NUM)
|
||||
break;
|
||||
|
||||
float max_cls_score = -1.0f;
|
||||
int cls_id = -1;
|
||||
|
||||
const float* score_ptr = &input_scores[i];
|
||||
for (j = 0; j < NUM_CLASSES; j++) {
|
||||
const float score = *score_ptr;
|
||||
if (score > max_cls_score) {
|
||||
max_cls_score = score;
|
||||
cls_id = j;
|
||||
}
|
||||
score_ptr += GRID_ROW_COUNT;
|
||||
}
|
||||
|
||||
if (cls_id != -1 && max_cls_score >= CONFIDENCE_THRESHOLD)
|
||||
{
|
||||
const float x_center = input_coords[offset_x + i];
|
||||
const float y_center = input_coords[offset_y + i];
|
||||
const float width = input_coords[offset_w + i];
|
||||
const float height = input_coords[offset_h + i];
|
||||
const float x = width * 0.5f;
|
||||
const float y = height * 0.5f;
|
||||
|
||||
det_before[valid_count].boxes.x = x_center - x;
|
||||
det_before[valid_count].boxes.y = y_center - y;
|
||||
det_before[valid_count].boxes.w = x_center + x;
|
||||
det_before[valid_count].boxes.h = y_center + y;
|
||||
det_before[valid_count].scores = max_cls_score;
|
||||
det_before[valid_count].classes = cls_id;
|
||||
valid_count++;
|
||||
}
|
||||
}
|
||||
|
||||
nms(det_before, dets, &valid_count, IOU_THRESHOLD);
|
||||
|
||||
return valid_count;
|
||||
}
|
||||
|
||||
int print_yolov8s_result(void *results, unsigned short nboxes)
|
||||
{
|
||||
int i = 0;
|
||||
int status = 0;
|
||||
detection *dets =(detection *)results;
|
||||
printf("Total detections: %d\n", nboxes);
|
||||
for (i = 0; i < nboxes; i++) {
|
||||
printf("%d %.2f %.2f %.2f %.2f %.2f\n",
|
||||
dets[i].classes,
|
||||
dets[i].scores,
|
||||
dets[i].boxes.x,
|
||||
dets[i].boxes.y,
|
||||
dets[i].boxes.w,
|
||||
dets[i].boxes.h);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* @Author: xun
|
||||
* @Date: 2025-02-14 10:22:55
|
||||
* @LastEditors: xun
|
||||
* @LastEditTime: 2025-05-09 14:14:20
|
||||
* @Description:
|
||||
* Copyright (c) 2025 by CCYH, All Rights Reserved.
|
||||
*/
|
||||
// yolov8s_post.h
|
||||
#ifndef _YOLOV8S_POST_H_
|
||||
#define _YOLOV8S_POST_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_DET_NUM 100
|
||||
|
||||
typedef struct box {
|
||||
float x, y, w, h;
|
||||
} box;
|
||||
|
||||
typedef struct detection {
|
||||
box boxes;
|
||||
float scores;
|
||||
int classes;
|
||||
} detection;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 执行YOLOv8模型后处理的函数
|
||||
*
|
||||
* 解析模型输出的坐标和分数数据,筛选有效检测框并进行非极大值抑制(NMS)
|
||||
*
|
||||
* @param dets [OUT] 检测结果数组,存储处理后的目标信息
|
||||
* @param counts [IN] 输入缓冲区指针数组,包含两个元素:
|
||||
* input_buffer[0]为坐标数据指针(格式:x_center, y_center, width, height)
|
||||
* input_buffer[1]为类别分数数据指针
|
||||
* @param counts [IN] 模型输出层数(此处应传入缓冲区数组长度,建议值为2)
|
||||
* @return int 成功时返回检测到的目标数量(>=0),若出现参数错误返回-1
|
||||
*/
|
||||
int yolov8s_postprocess(detection *dets, void **input_buffer, int counts);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 打印yolov8s后处理结果
|
||||
*
|
||||
* @param results [IN] 结果地址
|
||||
* @param nboxes [IN] 目标个数
|
||||
* @return int 返回处理后的状态码,0表示成功,-1表示失败
|
||||
*/
|
||||
int print_yolov8s_result(void *results, unsigned short nboxes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !_YOLOV8S_POST_H_
|
Binary file not shown.
After Width: | Height: | Size: 220 KiB |
Binary file not shown.
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* @Author: xun
|
||||
* @Date: 2024-09-03 16:02:39
|
||||
* @LastEditors: xun
|
||||
* @LastEditTime: 2025-05-12 09:40:00
|
||||
* @Description:
|
||||
* Copyright (c) 2024 by CCYH, All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------
|
||||
Includes
|
||||
-------------------------------------------*/
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "nn_api.h"
|
||||
#include "nn_utils.h"
|
||||
#include "quantize.h"
|
||||
#include "normalize.h"
|
||||
#include "preprocess.h"
|
||||
#include "postprocess/yolov8s_post.h"
|
||||
|
||||
|
||||
/*-------------------------------------------
|
||||
Macros and Variables
|
||||
-------------------------------------------*/
|
||||
|
||||
#define MAX_DIMS 2
|
||||
#define INPUT0_SIZE 640*640*3*2
|
||||
#define INPUT1_SIZE 0
|
||||
|
||||
#ifdef __linux__
|
||||
#define NETWORK_INPUT_TYPE_JPEG 1
|
||||
// #define NETWORK_INPUT_TYPE_TENSOR 1
|
||||
// #define NETWORK_INPUT_TYPE_BINARY 1
|
||||
#endif
|
||||
|
||||
#ifdef _TMS320C6X
|
||||
#include <c6x.h>
|
||||
#include "M6678E_PLL.h"
|
||||
#include "M6678E_PSC.h"
|
||||
#endif
|
||||
|
||||
const char *usage =
|
||||
"-n network.nb: network binary graph (NBG) data file resource.\n"
|
||||
"-i input nunber input_0.dat input_1.dat ...: nunber: input file number.\n"
|
||||
" input file name 1, input file name 2 ... \n"
|
||||
"-l loop_run_count: the number of loop run network.\n"
|
||||
"-t time_out: specify time out of network.\n"
|
||||
"-h : help \n"
|
||||
"example: ./test -n network_binary.nb -i 1 car.jpg \n";
|
||||
|
||||
|
||||
/*-------------------------------------------
|
||||
Main Functions
|
||||
-------------------------------------------*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0, k = 0;
|
||||
|
||||
// 初始化参数
|
||||
char *input_name[4] = { 0 };
|
||||
int input_count = 0;
|
||||
uint32_t loop_count = 1;
|
||||
uint32_t count = 0;
|
||||
uint32_t time_out = 0;
|
||||
nn_context *context = NULL;
|
||||
|
||||
//前处理参数
|
||||
void *input_data[MAX_DIMS] = { 0 };
|
||||
|
||||
// 后处理参数
|
||||
int nboxes = 0;
|
||||
void *output_data[MAX_DIMS] = { 0 };
|
||||
detection results[MAX_DET_NUM] = { 0 };
|
||||
|
||||
#ifdef __linux__
|
||||
char *nbg_name = NULL;
|
||||
if (argc < 2) {
|
||||
printf("%s\n", usage);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-l")) {
|
||||
loop_count = atoi(argv[++i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-n")) {
|
||||
nbg_name = argv[++i];
|
||||
}
|
||||
else if (!strcmp(argv[i], "-t")) {
|
||||
time_out = atoi(argv[++i]);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-i")) {
|
||||
input_count = atoi(argv[++i]);
|
||||
for (k = 0; k < input_count; k++) {
|
||||
input_name[k] = argv[++i];
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "-h")) {
|
||||
printf("%s\n", usage);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (NULL == nbg_name) {
|
||||
printf("%s\n", usage);
|
||||
return -1;
|
||||
}
|
||||
for (k = 0; k < input_count; k++) {
|
||||
if (NULL == input_name[k]) {
|
||||
printf("%s\n", usage);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
printf("test started.\n");
|
||||
printf("loop_count=%d, nbg_name=%s\n", loop_count, nbg_name);
|
||||
for (i = 0; i < input_count; i++) {
|
||||
printf("input_name: %s\n", input_name[i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _TMS320C6X
|
||||
char *nbg_name = "network_binary.nb";
|
||||
network_address = (uint32_t *)0xE0000000;
|
||||
input_dat0_address = (uint32_t *)0xE1000000;
|
||||
input_dat1_address = (uint32_t *)0xE2000000;
|
||||
my_network_size = 3816092;
|
||||
my_input_size = 519168;
|
||||
#endif
|
||||
|
||||
// 打开设备
|
||||
ret = pnna_open();
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// 初始化网络
|
||||
ret = nn_init(&context, nbg_name, time_out);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifndef NETWORK_INPUT_TYPE_JPEG
|
||||
const uint32_t input_sizes[] = {
|
||||
INPUT0_SIZE,
|
||||
INPUT1_SIZE
|
||||
};
|
||||
static_assert(
|
||||
sizeof(input_sizes)/sizeof(input_sizes[0]) == MAX_DIMS,
|
||||
"The length of the input_sizes must be equal to MAX_DIMS"
|
||||
);
|
||||
#endif
|
||||
|
||||
#ifdef NETWORK_INPUT_TYPE_JPEG
|
||||
void *input_tmp_data[MAX_DIMS] = { 0 };
|
||||
void *input_data_float[MAX_DIMS] = { 0 };
|
||||
normalization_params norm_params;
|
||||
int mean[3] = { 0 };
|
||||
int std[3] = {255, 255, 255};
|
||||
int reorder_channel[3] = {0, 1, 2};
|
||||
float scale = 1.0f / 255.0f;
|
||||
int width = 640;
|
||||
int height = 640;
|
||||
int channel = 3;
|
||||
int pic_size = width * height * channel;
|
||||
int norm_size = pic_size * sizeof(float);
|
||||
int jpg_temp_size = pic_size * sizeof(uint8_t);
|
||||
|
||||
// 设置输入图片的归一化参数
|
||||
set_normalize_params(&norm_params, width, height, channel, \
|
||||
mean, std, reorder_channel, scale);
|
||||
ret = create_buffers(input_tmp_data, input_count, &jpg_temp_size);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
ret = create_buffers(input_data_float, input_count, &norm_size);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#elif NETWORK_INPUT_TYPE_TENSOR
|
||||
int quant_size[MAX_DIMS] = { 0 };
|
||||
void *input_data_float[MAX_DIMS] = { 0 };
|
||||
for (i = 0; i < input_count; i++) {
|
||||
quant_size[i] = input_sizes[i]* sizeof(float);
|
||||
}
|
||||
ret = create_buffers(input_data_float, input_count, quant_size);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
// 为进入网络的 buffer 申请空间
|
||||
ret = create_buffers(input_data, input_count, context->input_size);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
int output_sizes[MAX_DIMS] = { 0 };
|
||||
void *output_data_float[MAX_DIMS] = { 0 };
|
||||
get_output_sizes(context, sizeof(float), output_sizes);
|
||||
|
||||
ret = create_buffers(output_data_float, context->output_count, output_sizes);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// 循环推理
|
||||
while(count < loop_count) {
|
||||
count++;
|
||||
// 准备数据
|
||||
#ifdef NETWORK_INPUT_TYPE_JPEG
|
||||
// 将JPEG图片解码为bmp图片
|
||||
ret = get_jpeg_data(input_name, width, height, channel, input_count, input_tmp_data);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// 归一化处理
|
||||
ret = preprocess(input_tmp_data, &norm_params, input_count, input_data_float);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// 量化处理
|
||||
ret = nn_quantize(context, (float **)input_data_float, input_data);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#elif NETWORK_INPUT_TYPE_TENSOR
|
||||
ret = get_tensor_data(input_data_float, input_name, input_count, input_sizes);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
// 量化处理
|
||||
ret = nn_quantize(context, (float **)input_data_float, input_data);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#elif NETWORK_INPUT_TYPE_BINARY
|
||||
ret = get_binary_data(input_data, input_name, input_count, input_sizes);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _TMS320C6X
|
||||
input_data[0] = input_dat0_address;
|
||||
#endif
|
||||
|
||||
// 开始推理
|
||||
ret = nn_infer(context, (void **)input_data, output_data);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
printf("run network done...\n");
|
||||
|
||||
// 获取推理时间
|
||||
ret = get_infer_time(context, 1);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
}
|
||||
float time = (float)context->infer_time / 1000.0f;
|
||||
printf("profile inference time=%fms, cycle=%d\n", time, context->infer_cycle);
|
||||
|
||||
// 后处理
|
||||
ret = nn_dequantize(context, output_data, (float **)output_data_float);
|
||||
if (ret != NN_SUCCESS) {
|
||||
print_msg(errno2str(ret));
|
||||
goto exit;
|
||||
}
|
||||
start_timing(0);
|
||||
nboxes = yolov8s_postprocess(results, output_data_float, context->output_count);
|
||||
end_timing(0);
|
||||
printf("yolov8s_postprocess spend: %f ms\n", get_time_ms(0));
|
||||
print_yolov8s_result(results, nboxes);
|
||||
}
|
||||
|
||||
exit:
|
||||
destroy_buffers(output_data_float, context->output_count);
|
||||
|
||||
#ifdef __linux__
|
||||
// 释放用户自定义资源
|
||||
destroy_buffers(input_data, input_count);
|
||||
#ifdef NETWORK_INPUT_TYPE_JPEG
|
||||
destroy_buffers(input_tmp_data, input_count);
|
||||
destroy_buffers(input_data_float, input_count);
|
||||
#elif NETWORK_INPUT_TYPE_TENSOR
|
||||
destroy_buffers(input_data_float, input_count);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 释放网络资源
|
||||
nn_destroy(context);
|
||||
// 关闭设备
|
||||
pnna_close();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue