调整目录结构,改为一个模型一个文件夹,Makefile文件增加log日志打印等级

This commit is contained in:
xunyingya 2025-07-28 09:02:23 +08:00
parent 17c17af53f
commit 8b7b08a54b
16 changed files with 1211 additions and 4 deletions

4
.gitignore vendored
View File

@ -2,9 +2,5 @@
/docs/
.vscode/
*.o
yolov8s
yolov5s
Makefile
Makefile-bak
Doxyfile
libpnna.a

49
resnet18/Makefile Normal file
View File

@ -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)

49
yolov4_tiny/Makefile Normal file
View File

@ -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)

49
yolov5s/Makefile Normal file
View File

@ -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)

View File

@ -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;
}

View File

@ -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_

BIN
yolov5s/resource/car.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

140
yolov5s/yolov5s_demo.c Normal file
View File

@ -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;
}

49
yolov5s_relu/Makefile Normal file
View File

@ -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)

49
yolov8s/Makefile Normal file
View File

@ -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)

View File

@ -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;
}

View File

@ -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_

BIN
yolov8s/resource/car.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

320
yolov8s/yolov8s_demo.c Normal file
View File

@ -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;
}