Upload first version

This commit is contained in:
dengliu1105 2026-01-06 10:29:54 +08:00
parent f95d5a63b0
commit 3bdf2003ec
898 changed files with 1405811 additions and 1 deletions

View file

View file

View file

@ -0,0 +1,77 @@
#!/bin/bash
set -e
#
# Copyright (C) 20242025 Amlogic, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
#
usage() {
echo "Usage: $0 [-a <target_abi>]"
echo " -a <target_abi> : Target ABI (default: arm64-v8a)"
echo " -h : Show this help message"
exit 1
}
# Default values
TARGET_ABI=arm64-v8a
# Parse arguments
while getopts 'a:h' opt; do
case "$opt" in
a)
TARGET_ABI=$OPTARG
;;
h)
usage
;;
*)
usage
;;
esac
done
if [ -z "${ANDROID_NDK_PATH}" ]; then
if [ -n "${ANDROID_NDK}" ]; then
ANDROID_NDK_PATH=${ANDROID_NDK}
elif [ -n "${ANDROID_NDK_HOME}" ]; then
ANDROID_NDK_PATH=${ANDROID_NDK_HOME}
else
echo "Error: ANDROID_NDK_PATH is not set."
echo "Please set ANDROID_NDK_PATH to your Android NDK directory."
exit 1
fi
fi
ROOT_PWD=$(cd "$(dirname $0)" && pwd)
BUILD_DIR=${ROOT_PWD}/build/android
echo "Building for Android..."
echo "NDK_PATH: ${ANDROID_NDK_PATH}"
echo "TARGET_ABI: ${TARGET_ABI}"
echo "BUILD_DIR: ${BUILD_DIR}"
mkdir -p ${BUILD_DIR}
cd ${BUILD_DIR}
cmake ../../src \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_PATH}/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=${TARGET_ABI} \
-DANDROID_PLATFORM=android-24 \
-DCMAKE_BUILD_TYPE=Release \
-DOpenCV_DIR=${ROOT_PWD}/../../../dependency/opencv/opencv-android-sdk-build/sdk/native/jni/abi-${TARGET_ABI}
make -j4
echo "Build complete. Executable in ${BUILD_DIR}/yolo11_demo"

View file

@ -0,0 +1,65 @@
#TODO
#!/bin/bash
set -e
usage() {
echo "Usage: $0 [-a <target_arch>]"
echo " -a <target_arch> : Target architecture (default: aarch64)"
echo " -h : Show this help message"
exit 1
}
# Default values
TARGET_ARCH=aarch64
# Parse arguments
while getopts 'a:h' opt; do
case "$opt" in
a)
TARGET_ARCH=$OPTARG
;;
h)
usage
;;
*)
usage
;;
esac
done
# Default to aarch64-linux-gnu if GCC_COMPILER is not set
GCC_COMPILER=${GCC_COMPILER:-aarch64-linux-gnu}
# Set compilers
export CC=${GCC_COMPILER}-gcc
export CXX=${GCC_COMPILER}-g++
# Validate compiler
if ! command -v ${CC} &> /dev/null; then
echo "Error: Compiler ${CC} not found."
echo "Please set GCC_COMPILER environment variable to your cross-compiler path prefix."
echo "Example: export GCC_COMPILER=/path/to/toolchain/bin/aarch64-linux-gnu"
# Proceeding anyway as user might have custom env setup
else
echo "Using compiler: ${CC}"
fi
ROOT_PWD=$(cd "$(dirname $0)" && pwd)
BUILD_DIR=${ROOT_PWD}/build/linux
echo "Building for Linux..."
echo "COMPILER: ${CC}"
echo "TARGET_ARCH: ${TARGET_ARCH}"
echo "BUILD_DIR: ${BUILD_DIR}"
mkdir -p ${BUILD_DIR}
cd ${BUILD_DIR}
cmake ../../src \
-DCMAKE_SYSTEM_NAME=Linux \
-DCMAKE_SYSTEM_PROCESSOR=${TARGET_ARCH} \
-DCMAKE_BUILD_TYPE=Release \
-DOpenCV_DIR=${ROOT_PWD}/../../../dependency/opencv/opencv-linux-aarch64/share/OpenCV
make -j4
echo "Build complete. Executable in ${BUILD_DIR}/yolo11_demo"

View file

@ -0,0 +1,41 @@
cmake_minimum_required(VERSION 3.5)
project(yolo11_demo)
set(CMAKE_CXX_STANDARD 17)
# Set NNSDK path
set(NNSDK_ROOT "${CMAKE_SOURCE_DIR}/../../../../dependency/nnsdk")
include_directories(${NNSDK_ROOT}/include)
include_directories(${CMAKE_SOURCE_DIR}/../../../../common)
# Set dependency path
set(3RDPARTY_DIR "${CMAKE_SOURCE_DIR}/../../../../dependency")
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
if (ANDROID_ABI STREQUAL "arm64-v8a")
link_directories(${NNSDK_ROOT}/lib/android/arm64-v8a)
else()
link_directories(${NNSDK_ROOT}/lib/android/armeabi-v7a)
endif()
# Android needs log
link_libraries(log)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
link_directories(${NNSDK_ROOT}/lib/linux/lib64_yocto)
endif()
# Find OpenCV
message(STATUS "OpenCV_DIR: ${OpenCV_DIR}")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(yolo11_demo
main.cpp
postprocess.cpp
${CMAKE_SOURCE_DIR}/../../../../common/model_loader.cpp
)
target_link_libraries(yolo11_demo
${OpenCV_LIBS}
nnsdk
)

111
examples/yolov11/cpp/src/main.cpp Executable file
View file

@ -0,0 +1,111 @@
#include <iostream>
#include <vector>
#include <filesystem>
#include <opencv2/opencv.hpp>
#include <float.h>
#include "nn_sdk.h"
#include "postprocess.h"
namespace fs = std::filesystem;
static void hwc_to_chw(const cv::Mat& src, float* dst) {
int h = src.rows, w = src.cols;
for (int k = 0; k < 3; ++k) {
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
dst[k * h * w + i * w + j] = src.at<cv::Vec3f>(i, j)[k];
}
}
}
}
int main(int argc, char** argv) {
if (argc < 3) { std::cout << "Usage: " << argv[0] << " <model.adla> <image_dir>\n"; return 0; }
aml_config cfg{};
cfg.typeSize = sizeof(cfg); cfg.modelType = ADLA_LOADABLE; cfg.nbgType = NN_ADLA_FILE; cfg.path = argv[1];
void* ctx = aml_module_create(&cfg);
if (!ctx) return -1;
std::vector<float> chw_buffer(kInputW * kInputH * 3);
fs::create_directory("yolo11_result");
for (auto& it : fs::directory_iterator(argv[2])) {
cv::Mat img = cv::imread(it.path().string());
if (img.empty()) continue;
std::cout << "============================================================" << std::endl;
std::cout << "Processing image: \"" << it.path().filename().string() << "\"" << std::endl;
std::cout << "============================================================" << std::endl;
float scale = std::min((float)kInputW / img.cols, (float)kInputH / img.rows);
int nw = img.cols * scale, nh = img.rows * scale;
int px = (kInputW - nw) / 2, py = (kInputH - nh) / 2;
cv::Mat res, canvas = cv::Mat::zeros(kInputH, kInputW, CV_32FC3);
canvas.setTo(cv::Scalar(114.0/255.0, 114.0/255.0, 114.0/255.0));
cv::resize(img, res, {nw, nh});
res.convertTo(res, CV_32FC3, 1.0 / 255.0);
res.copyTo(canvas(cv::Rect(px, py, nw, nh)));
hwc_to_chw(canvas, chw_buffer.data());
nn_input in{}; in.typeSize = sizeof(in); in.input_type = BINARY_RAW_DATA;
in.input = (unsigned char*)chw_buffer.data(); in.size = chw_buffer.size() * 4;
in.info.valid = 1; in.info.input_format = AML_INPUT_MODEL_NCHW; in.info.input_data_type = AML_INPUT_FP32;
aml_module_input_set(ctx, &in);
aml_output_config_t outcfg{}; outcfg.typeSize = sizeof(outcfg); outcfg.format = AML_OUTDATA_FLOAT32;
nn_output* out = (nn_output*)aml_module_output_get(ctx, outcfg);
if (!out) continue;
std::vector<cv::Rect> bboxes;
std::vector<float> confs;
std::vector<int> class_ids;
std::vector<int> strides = {32, 16, 8};
for (int i = 0; i < out->num; i++) {
float* data = (float*)out->out[i].buf;
int stride = strides[i], grid_h = kInputH / stride, grid_w = kInputW / stride;
for (int g = 0; g < grid_h * grid_w; g++) {
float* feat = data + g * kTotalChannels;
float max_score = -1.0f; int cls_id = -1;
for (int c = 0; c < kNumClasses; c++) {
float score = 1.0f / (1.0f + std::exp(-feat[64 + c]));
if (score > max_score) { max_score = score; cls_id = c; }
}
if (max_score > 0.3f) {
float d_l = decode_dfl(feat + 0), d_t = decode_dfl(feat + 16);
float d_r = decode_dfl(feat + 32), d_b = decode_dfl(feat + 48);
float cx = (g % grid_w) + 0.5f, cy = (g / grid_w) + 0.5f;
int rx1 = std::max(0, (int)(((cx - d_l) * stride - px) / scale));
int ry1 = std::max(0, (int)(((cy - d_t) * stride - py) / scale));
int rx2 = std::min(img.cols, (int)(((cx + d_r) * stride - px) / scale));
int ry2 = std::min(img.rows, (int)(((cy + d_b) * stride - py) / scale));
bboxes.push_back(cv::Rect(rx1, ry1, rx2 - rx1, ry2 - ry1));
confs.push_back(max_score); class_ids.push_back(cls_id);
}
}
}
std::vector<int> indices = manual_nms(bboxes, confs, 0.45f);
if (!indices.empty()) {
std::cout << "Detected " << indices.size() << " objects:" << std::endl;
for (size_t i = 0; i < indices.size(); i++) {
int idx = indices[i];
printf(" %zu. %s (%.2f)\n", i + 1, kClassNames[class_ids[idx]].c_str(), confs[idx]);
cv::rectangle(img, bboxes[idx], {0, 255, 0}, 2);
char text[256]; std::sprintf(text, "%s %.2f", kClassNames[class_ids[idx]].c_str(), confs[idx]);
cv::putText(img, text, {bboxes[idx].x, bboxes[idx].y - 5}, cv::FONT_HERSHEY_SIMPLEX, 0.5, {0, 255, 0}, 1);
}
} else {
std::cout << "No objects detected." << std::endl;
}
std::string out_path = "yolo11_result/" + it.path().filename().string();
cv::imwrite(out_path, img);
std::cout << "Result saved to: " << out_path << std::endl;
std::cout << "============================================================" << std::endl << std::endl;
}
aml_module_destroy(ctx); return 0;
}

View file

@ -0,0 +1,66 @@
#include "postprocess.h"
#include <cmath>
#include <numeric>
#include <algorithm>
#include <float.h>
const std::vector<std::string> kClassNames = {
"person", "bicycle", "car", "motorcycle", "airplane", "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", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard",
"cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase",
"scissors", "teddy bear", "hair drier", "toothbrush"
};
float decode_dfl(const float* dfl_ptr) {
float max_val = -FLT_MAX;
for (int i = 0; i < kDflChannels; i++) {
if (dfl_ptr[i] > max_val) max_val = dfl_ptr[i];
}
float exp_sum = 0;
float exp_vals[kDflChannels];
for (int i = 0; i < kDflChannels; i++) {
exp_vals[i] = std::exp(dfl_ptr[i] - max_val);
exp_sum += exp_vals[i];
}
float res = 0;
for (int i = 0; i < kDflChannels; i++) {
res += (exp_vals[i] / exp_sum) * i;
}
return res;
}
float calculate_iou(const cv::Rect& a, const cv::Rect& b) {
int xx1 = std::max(a.x, b.x);
int yy1 = std::max(a.y, b.y);
int xx2 = std::min(a.x + a.width, b.x + b.width);
int yy2 = std::min(a.y + a.height, b.y + b.height);
int w = std::max(0, xx2 - xx1);
int h = std::max(0, yy2 - yy1);
float inter = (float)w * h;
float areaA = (float)a.width * a.height;
float areaB = (float)b.width * b.height;
return inter / (areaA + areaB - inter);
}
std::vector<int> manual_nms(const std::vector<cv::Rect>& boxes, const std::vector<float>& scores, float thresh) {
std::vector<int> order(boxes.size());
std::iota(order.begin(), order.end(), 0);
std::stable_sort(order.begin(), order.end(), [&](int a, int b) {
return scores[a] > scores[b];
});
std::vector<int> keep;
while (!order.empty()) {
int i = order[0];
keep.push_back(i);
order.erase(order.begin());
order.erase(std::remove_if(order.begin(), order.end(), [&](int j) {
return calculate_iou(boxes[i], boxes[j]) > thresh;
}), order.end());
}
return keep;
}

View file

@ -0,0 +1,26 @@
#ifndef YOLO11_POSTPROCESS_H
#define YOLO11_POSTPROCESS_H
#include <vector>
#include <string>
#include <opencv2/opencv.hpp>
static constexpr int kInputW = 640;
static constexpr int kInputH = 640;
static constexpr int kNumClasses = 80;
static constexpr int kDflChannels = 16;
static constexpr int kTotalChannels = 144;
extern const std::vector<std::string> kClassNames;
struct Detection {
cv::Rect box;
float confidence;
int class_id;
};
float decode_dfl(const float* dfl_ptr);
float calculate_iou(const cv::Rect& a, const cv::Rect& b);
std::vector<int> manual_nms(const std::vector<cv::Rect>& boxes, const std::vector<float>& scores, float thresh);
#endif

View file

View file