diff --git a/docs/ax650/yolov8s_obb_out.jpg b/docs/ax650/yolov8s_obb_out.jpg
new file mode 100644
index 0000000..998f6ca
Binary files /dev/null and b/docs/ax650/yolov8s_obb_out.jpg differ
diff --git a/examples/ax650/CMakeLists.txt b/examples/ax650/CMakeLists.txt
index 14541a4..f14c41a 100644
--- a/examples/ax650/CMakeLists.txt
+++ b/examples/ax650/CMakeLists.txt
@@ -33,6 +33,7 @@ axera_example(ax_yolov8 ax_yolov8_steps.cc)
axera_example(ax_yolov8_nv12 ax_yolov8_nv12_steps.cc)
axera_example(ax_yolov8_seg ax_yolov8_seg_steps.cc)
axera_example(ax_yolov8_pose ax_yolov8_pose_steps.cc)
+axera_example(ax_yolov8_obb ax_yolov8_obb_steps.cc)
axera_example(ax_yolox ax_yolox_steps.cc)
axera_example(ax_yolo_nas ax_yolo_nas_steps.cc)
diff --git a/examples/ax650/README.md b/examples/ax650/README.md
index ae608d7..6623b4b 100644
--- a/examples/ax650/README.md
+++ b/examples/ax650/README.md
@@ -605,4 +605,62 @@ detection num: 5
16: 69%, [ 144, 203, 195, 343], dog
--------------------------------------
```
-
\ No newline at end of file
+
+
+### YOLOV8-OBB
+```
+/opt/test # ./ax_yolov8_obb -m ./yolov8s-obb.axmodel -i ./dota_demo.jpg -r 10
+--------------------------------------
+model file : ./yolov8s-obb.axmodel
+image file : ./dota_demo.jpg
+img_h, img_w : 1024 1024
+--------------------------------------
+Engine creating handle is done.
+Engine creating context is done.
+Engine get io info is done.
+Engine alloc io is done.
+Engine push input is done.
+--------------------------------------
+post process cost time:6.04 ms
+--------------------------------------
+Repeat 10 times, avg time 26.66 ms, max_time 26.71 ms, min_time 26.62 ms
+--------------------------------------
+detection num: 35
+ 0: 93%, [ 691, 632, 766, 697], plane
+ 0: 93%, [ 642, 579, 701, 634], plane
+ 0: 93%, [ 392, 318, 466, 382], plane
+ 0: 93%, [ 272, 191, 375, 281], plane
+ 0: 91%, [ 342, 260, 443, 347], plane
+ 0: 91%, [ 421, 593, 498, 660], plane
+ 0: 91%, [ 182, 409, 279, 501], plane
+ 0: 91%, [ 591, 522, 693, 608], plane
+ 0: 91%, [ 832, 781, 942, 857], plane
+10: 84%, [ 99, 710, 120, 720], small vehicle
+10: 84%, [ 25, 834, 45, 843], small vehicle
+10: 79%, [ 173, 724, 192, 733], small vehicle
+10: 79%, [ 29, 715, 50, 725], small vehicle
+10: 79%, [ 26, 823, 47, 832], small vehicle
+10: 79%, [ 101, 733, 119, 743], small vehicle
+10: 79%, [ 171, 704, 191, 714], small vehicle
+10: 79%, [ 100, 662, 120, 671], small vehicle
+10: 79%, [ 101, 686, 119, 696], small vehicle
+10: 79%, [ 23, 867, 42, 876], small vehicle
+10: 73%, [ 25, 884, 44, 895], small vehicle
+10: 73%, [ 167, 835, 185, 845], small vehicle
+10: 73%, [ 100, 672, 119, 682], small vehicle
+10: 73%, [ 100, 697, 119, 707], small vehicle
+10: 73%, [ 31, 702, 53, 712], small vehicle
+10: 73%, [ 25, 800, 41, 811], small vehicle
+10: 73%, [ 31, 757, 60, 767], small vehicle
+10: 66%, [ 23, 845, 40, 853], small vehicle
+10: 66%, [ 165, 903, 187, 914], small vehicle
+10: 58%, [ 98, 450, 122, 461], small vehicle
+10: 58%, [ 23, 856, 40, 865], small vehicle
+10: 50%, [ 170, 771, 186, 780], small vehicle
+10: 50%, [ 28, 733, 48, 745], small vehicle
+10: 50%, [ 168, 925, 188, 936], small vehicle
+10: 50%, [ 102, 746, 120, 755], small vehicle
+10: 27%, [ 91, 461, 116, 474], small vehicle
+--------------------------------------
+```
+![yolov8-obb](../../docs/ax650/yolov8s_obb_out.jpg)
\ No newline at end of file
diff --git a/examples/ax650/ax_yolov8_obb_steps.cc b/examples/ax650/ax_yolov8_obb_steps.cc
new file mode 100644
index 0000000..95bf254
--- /dev/null
+++ b/examples/ax650/ax_yolov8_obb_steps.cc
@@ -0,0 +1,244 @@
+/*
+* AXERA is pleased to support the open source community by making ax-samples available.
+*
+* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
+*
+* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
+* in compliance with the License. You may obtain a copy of the License at
+*
+* https://opensource.org/licenses/BSD-3-Clause
+*
+* Unless required by applicable law or agreed to in writing, software distributed
+* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+* CONDITIONS OF ANY KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations under the License.
+*/
+
+/*
+* Author: FeiGeChuanShu
+*/
+
+#include
+#include
+#include
+
+#include
+#include "base/common.hpp"
+#include "base/detection.hpp"
+#include "middleware/io.hpp"
+
+#include "utilities/args.hpp"
+#include "utilities/cmdline.hpp"
+#include "utilities/file.hpp"
+#include "utilities/timer.hpp"
+
+#include
+#include
+
+const int DEFAULT_IMG_H = 1024;
+const int DEFAULT_IMG_W = 1024;
+
+static const char* CLASS_NAMES[] = {
+ "plane", "ship", "storage tank", "baseball diamond", "tennis court",
+ "basketball court", "ground track field", "harbor", "bridge", "large vehicle",
+ "small vehicle", "helicopter", "roundabout", "soccer ball field", "swimming pool"
+};
+
+int NUM_CLASS = 15;
+
+const int DEFAULT_LOOP_COUNT = 1;
+
+const float PROB_THRESHOLD = 0.25f;
+const float NMS_THRESHOLD = 0.45f;
+namespace ax
+{
+ void post_process(AX_ENGINE_IO_INFO_T* io_info, AX_ENGINE_IO_T* io_data, const cv::Mat& mat, int input_w, int input_h, const std::vector& time_costs)
+ {
+ std::vector proposals;
+ std::vector objects;
+ timer timer_postprocess;
+
+ std::vector strides = { 8, 16, 32 };
+ std::vector grid_strides;
+ detection::generate_grids_and_stride(input_w, input_h, strides, grid_strides);
+
+ auto feat_ptr = (float*)io_data->pOutputs[0].pVirAddr;
+ detection::obb::generate_proposals_yolov8_obb_native(grid_strides, feat_ptr, PROB_THRESHOLD, proposals, input_w, input_h, NUM_CLASS);
+ detection::obb::get_out_obb_bbox(proposals, objects, NMS_THRESHOLD, input_h, input_w, mat.rows, mat.cols);
+
+ fprintf(stdout, "post process cost time:%.2f ms \n", timer_postprocess.cost());
+ fprintf(stdout, "--------------------------------------\n");
+ auto total_time = std::accumulate(time_costs.begin(), time_costs.end(), 0.f);
+ auto min_max_time = std::minmax_element(time_costs.begin(), time_costs.end());
+ fprintf(stdout,
+ "Repeat %d times, avg time %.2f ms, max_time %.2f ms, min_time %.2f ms\n",
+ (int)time_costs.size(),
+ total_time / (float)time_costs.size(),
+ *min_max_time.second,
+ *min_max_time.first);
+ fprintf(stdout, "--------------------------------------\n");
+ fprintf(stdout, "detection num: %zu\n", objects.size());
+
+ detection::obb::draw_objects_obb(mat, objects, CLASS_NAMES, "yolov8s_obb_out", 1);
+ }
+
+ bool run_model(const std::string& model, const std::vector& data, const int& repeat, cv::Mat& mat, int input_h, int input_w)
+ {
+ // 1. init engine
+#ifdef AXERA_TARGET_CHIP_AX620E
+ auto ret = AX_ENGINE_Init();
+#else
+ AX_ENGINE_NPU_ATTR_T npu_attr;
+ memset(&npu_attr, 0, sizeof(npu_attr));
+ npu_attr.eHardMode = AX_ENGINE_VIRTUAL_NPU_DISABLE;
+ auto ret = AX_ENGINE_Init(&npu_attr);
+#endif
+ if (0 != ret)
+ {
+ return ret;
+ }
+
+ // 2. load model
+ std::vector model_buffer;
+ if (!utilities::read_file(model, model_buffer))
+ {
+ fprintf(stderr, "Read Run-Joint model(%s) file failed.\n", model.c_str());
+ return false;
+ }
+
+ // 3. create handle
+ AX_ENGINE_HANDLE handle;
+ ret = AX_ENGINE_CreateHandle(&handle, model_buffer.data(), model_buffer.size());
+ SAMPLE_AX_ENGINE_DEAL_HANDLE
+ fprintf(stdout, "Engine creating handle is done.\n");
+
+ // 4. create context
+ ret = AX_ENGINE_CreateContext(handle);
+ SAMPLE_AX_ENGINE_DEAL_HANDLE
+ fprintf(stdout, "Engine creating context is done.\n");
+
+ // 5. set io
+ AX_ENGINE_IO_INFO_T* io_info;
+ ret = AX_ENGINE_GetIOInfo(handle, &io_info);
+ SAMPLE_AX_ENGINE_DEAL_HANDLE
+ fprintf(stdout, "Engine get io info is done. \n");
+
+ // 6. alloc io
+ AX_ENGINE_IO_T io_data;
+ ret = middleware::prepare_io(io_info, &io_data, std::make_pair(AX_ENGINE_ABST_DEFAULT, AX_ENGINE_ABST_CACHED));
+ SAMPLE_AX_ENGINE_DEAL_HANDLE
+ fprintf(stdout, "Engine alloc io is done. \n");
+
+ // 7. insert input
+ ret = middleware::push_input(data, &io_data, io_info);
+ SAMPLE_AX_ENGINE_DEAL_HANDLE_IO
+ fprintf(stdout, "Engine push input is done. \n");
+ fprintf(stdout, "--------------------------------------\n");
+
+ // 8. warn up
+ for (int i = 0; i < 5; ++i)
+ {
+ AX_ENGINE_RunSync(handle, &io_data);
+ }
+
+ // 9. run model
+ std::vector time_costs(repeat, 0);
+ for (int i = 0; i < repeat; ++i)
+ {
+ timer tick;
+ ret = AX_ENGINE_RunSync(handle, &io_data);
+ time_costs[i] = tick.cost();
+ SAMPLE_AX_ENGINE_DEAL_HANDLE_IO
+ }
+
+ // 10. get result
+ post_process(io_info, &io_data, mat, input_w, input_h, time_costs);
+ fprintf(stdout, "--------------------------------------\n");
+
+ middleware::free_io(&io_data);
+ return AX_ENGINE_DestroyHandle(handle);
+ }
+} // namespace ax
+
+int main(int argc, char* argv[])
+{
+ cmdline::parser cmd;
+ cmd.add("model", 'm', "joint file(a.k.a. joint model)", true, "");
+ cmd.add("image", 'i', "image file", true, "");
+ cmd.add("size", 'g', "input_h, input_w", false, std::to_string(DEFAULT_IMG_H) + "," + std::to_string(DEFAULT_IMG_W));
+
+ cmd.add("repeat", 'r', "repeat count", false, DEFAULT_LOOP_COUNT);
+ cmd.parse_check(argc, argv);
+
+ // 0. get app args, can be removed from user's app
+ auto model_file = cmd.get("model");
+ auto image_file = cmd.get("image");
+
+ auto model_file_flag = utilities::file_exist(model_file);
+ auto image_file_flag = utilities::file_exist(image_file);
+
+ if (!model_file_flag | !image_file_flag)
+ {
+ auto show_error = [](const std::string& kind, const std::string& value) {
+ fprintf(stderr, "Input file %s(%s) is not exist, please check it.\n", kind.c_str(), value.c_str());
+ };
+
+ if (!model_file_flag) { show_error("model", model_file); }
+ if (!image_file_flag) { show_error("image", image_file); }
+
+ return -1;
+ }
+
+ auto input_size_string = cmd.get("size");
+
+ std::array input_size = {DEFAULT_IMG_H, DEFAULT_IMG_W};
+
+ auto input_size_flag = utilities::parse_string(input_size_string, input_size);
+
+ if (!input_size_flag)
+ {
+ auto show_error = [](const std::string& kind, const std::string& value) {
+ fprintf(stderr, "Input %s(%s) is not allowed, please check it.\n", kind.c_str(), value.c_str());
+ };
+
+ show_error("size", input_size_string);
+
+ return -1;
+ }
+
+ auto repeat = cmd.get("repeat");
+
+ // 1. print args
+ fprintf(stdout, "--------------------------------------\n");
+ fprintf(stdout, "model file : %s\n", model_file.c_str());
+ fprintf(stdout, "image file : %s\n", image_file.c_str());
+ fprintf(stdout, "img_h, img_w : %d %d\n", input_size[0], input_size[1]);
+ fprintf(stdout, "--------------------------------------\n");
+
+ // 2. read image & resize & transpose
+ std::vector image(input_size[0] * input_size[1] * 3, 0);
+ cv::Mat mat = cv::imread(image_file);
+ if (mat.empty())
+ {
+ fprintf(stderr, "Read image failed.\n");
+ return -1;
+ }
+ common::get_input_data_letterbox(mat, image, input_size[0], input_size[1]);
+
+ // 3. sys_init
+ AX_SYS_Init();
+
+ // 4. - engine model - can only use AX_ENGINE** inside
+ {
+ // AX_ENGINE_NPUReset(); // todo ??
+ ax::run_model(model_file, image, repeat, mat, input_size[0], input_size[1]);
+
+ // 4.3 engine de init
+ AX_ENGINE_Deinit();
+ // AX_ENGINE_NPUReset();
+ }
+ // 4. - engine model -
+
+ AX_SYS_Deinit();
+ return 0;
+}
diff --git a/examples/base/detection.hpp b/examples/base/detection.hpp
index 72cae5a..575b0c0 100644
--- a/examples/base/detection.hpp
+++ b/examples/base/detection.hpp
@@ -45,6 +45,8 @@ namespace detection
cv::Mat mask;
std::vector mask_feat;
std::vector kps_feat;
+ /* for yolov8-obb */
+ float angle;
} Object;
/* for palm detection */
@@ -1311,7 +1313,7 @@ namespace detection
}
}
}
-
+
static void generate_proposals_yolov8_native(int stride, const float* feat, float prob_threshold, std::vector