快速集成
5 分钟将 ACL Pack 集成到 Android arm64-v8a 或 Linux aarch64 项目。
环境要求
通用
- C++17 编译器(商业版 libacl.a 以
-std=c++17构建,客户工程也需 ≥ C++17) - 你平台对应的 ACL Pack SDK zip(Android 或 Linux,两个独立 SKU 分开发售)
- 随 SDK 一起发货的
license.dat(包括 Trial 在内所有 tier 都必须)
Android 目标
- Android NDK 26.1+(Clang 工具链)
- arm64-v8a 目标设备或模拟器
Linux 目标
gcc-aarch64-linux-gnu9+(Ubuntu 20.04 默认 9.4) 或等效的 clang 交叉工具链- aarch64 glibc 目标系统(Jetson / RK3588 / 树莓派 4+ / 任意跑 glibc Linux 的 ARM64 嵌入式板)
Android arm64-v8a
1. 添加到项目
将 SDK 文件复制到项目目录:
your_project/
include/acl/ ← 从 SDK 复制
lib/arm64-v8a/libacl.a ← 从 SDK 复制
your_code.cpp2. 构建配置
Android.mk
LOCAL_PATH := $(call my-dir)
# ACL Pack 静态库
include $(CLEAR_VARS)
LOCAL_MODULE := acl
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libacl.a
include $(PREBUILT_STATIC_LIBRARY)
# 你的模块
include $(CLEAR_VARS)
LOCAL_MODULE := your_module
LOCAL_SRC_FILES := your_code.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_STATIC_LIBRARIES := acl
LOCAL_LDLIBS := -lm
include $(BUILD_SHARED_LIBRARY)或使用 CMake
add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/${ANDROID_ABI}/libacl.a)
target_include_directories(your_target PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(your_target acl m)或直接 NDK 命令
$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android25-clang++ \
-O2 -std=c++17 -Iinclude -o demo demo.cpp lib/arm64-v8a/libacl.a -lm3. 初始化
#include <acl/acl.h>
// 应用启动时调用一次。每个 tier(包括 Trial)都附带对应的 license 文件,
// 传入随 SDK 一起发给你的路径即可。
int ret = acl::init("/path/to/license.dat");
if (ret != 0) {
// 处理授权错误(错误码见 <acl/err.h>)
}完整 init 签名还接受可选的 Android JNIEnv* 和 jobject(应用上下文), 用于将授权状态与运行 JVM 绑定的部署场景。普通 native 使用保持默认 nullptr:
namespace acl {
int init(const char* licensePath, JNIEnv* env = nullptr, jobject context = nullptr);
const char* version(); // 返回 "1.0.3"
}Linux aarch64
1. 添加到项目
将 SDK 文件复制到项目目录:
your_project/
include/acl/ ← 从 SDK 复制
lib/linux-aarch64/libacl.a ← 从 SDK 复制
your_code.cpp2. 构建配置
直接交叉编译命令(最简单)
aarch64-linux-gnu-g++ \
-O2 -std=c++17 -Iinclude \
-o demo demo.cpp lib/linux-aarch64/libacl.a \
-lm -lpthread或使用 CMake + toolchain 文件
建立 toolchains/linux-aarch64.cmake:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
add_compile_options(-march=armv8-a)然后在 CMakeLists.txt 里:
add_library(acl STATIC IMPORTED)
set_target_properties(acl PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/lib/linux-aarch64/libacl.a)
target_include_directories(your_target PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(your_target acl m pthread)用以下命令配置:
cmake -DCMAKE_TOOLCHAIN_FILE=toolchains/linux-aarch64.cmake -DCMAKE_BUILD_TYPE=Release ..3. 初始化
#include <acl/acl.h>
// 应用启动时调用一次。
int ret = acl::init("/path/to/license.dat");
if (ret != 0) {
// 处理授权错误(错误码见 <acl/err.h>)
}Linux 构建可忽略 JNIEnv* / jobject 参数(默认 nullptr),传 license 路径即可。签名与 Android 一致:
namespace acl {
int init(const char* licensePath, JNIEnv* env = nullptr, jobject context = nullptr);
const char* version(); // 返回 "1.0.3"
}第一个 API 调用
Trial tier
Trial 仅提供 2 个固定参数的入口(在 <acl/api.h> 中,命名空间 acl::trial::):双线性 2× 下采样 — 有 _cpp 和 _neon 两个变体。输入必须恰好为 1920×1280 uint8 单通道,其他尺寸返回 ACL_ERR_RESOLUTION_LIMIT (-1006)。输出带 "ACL Pack Trial" 水印。
下面展示的通用 API 适用于 Starter / Pro / Business 三个付费 tier。
NEON 简化版(3x3 / 5x5 / 11x11 固定内核,最快路径)
#include <acl/api.h> // 所有算子声明都在这一个头里
// 对 640x480 灰度图做 3x3 高斯模糊
uint8_t* src = /* 你的图像数据 */;
uint8_t* dst = new uint8_t[640 * 480];
int result = acl::neon::filter::gaussianBlur3x3(src, dst, 640, 480);
if (result != 0) {
// 处理错误(例如 ACL_ERR_INVAL = -2 表示参数错误)
}
delete[] dst;完整签名(所有 kernel size 共用同一模式):
int gaussianBlur3x3(const uint8_t* srcImage, uint8_t* dstImage,
int width, int height,
int srcStride = 0, int dstStride = 0,
uint8_t constant = 0,
acl::BorderType bt = acl::BorderType::BORDER_REFLECT_101);同类 NEON 入口(1 通道 uint8):
gaussianBlur3x3、gaussianBlur5x5、gaussianBlur11x11— 签名一致,kernel 大小不同gaussianBlur3x3_3ch、gaussianBlur5x5_3ch— 3 通道变体(RGB / BGR)gaussianBlur(src, dst, w, h, srcStride, dstStride, kRadiusX, kRadiusY, sigmaX=0, sigmaY=0, constant=0, bt=BORDER_REFLECT_101)— 任意半径/sigma 的通用入口(仅 1 通道 uint8;sigma=0 且 kernel 大小匹配时内部分派到 3x3 / 5x5 / 11x11 快速路径,否则 fallback 到sepFilter2D)
CPP 通用版(任意半径 / sigma)
#include <acl/api.h> // 同一个头 — scalar 入口在 acl::filter:: 命名空间下
// 对 640x480 灰度图做 5x5 高斯模糊(自定义 sigma)
uint8_t* src = /* 你的图像数据 */;
uint8_t* dst = new uint8_t[640 * 480];
int result = acl::filter::gaussianBlur<uint8_t, uint8_t>(
src, dst,
640, 480, // width, height
1, // cn(通道数,1 = 灰度)
0, 0, // srcStride, dstStride (0 = 连续)
2, 2, // kRadiusX, kRadiusY(2 = 5x5 内核)
1.5, 1.5, // sigmaX, sigmaY (double)
nullptr, // constant (nullptr = 默认 BORDER 填充值)
acl::BorderType::BORDER_REFLECT_101 // bt
);
delete[] dst;CPP 版是可移植 scalar 路径,功能与 NEON 等价,但不走向量化。
核心概念
Stride(步幅)
Stride 是每行的字节数。对于连续内存,stride = width * channels * sizeof(type)。传 0 表示自动计算。
NEON 与 CPP 层
acl::neon::*— ARM NEON 向量化版,性能最优,仅 ARM64(Android arm64-v8a 与 Linux aarch64 都在列)acl::{module}::*— 可移植 C++ scalar 版,功能与 NEON 等价,用于功能验证或未向量化路径 fallback
单头文件,两套命名空间
所有算子声明都在一个头文件 <acl/api.h> 里。 客户只需 #include <acl/api.h>,通过命名空间区分:
acl::neon::{module}::op(...)→ NEON 向量化版acl::{module}::op(...)→ 可移植 scalar 版(注意命名空间不含cpp::段,虽然我们内部把这条路径叫做 "CPP 层")
工具模块(math、utils、memory::AutoBuffer 等)是特例,位于 acl::{module}:: 下(如 acl::memory::),不带 neon:: 前缀。
内核半径
ACL Pack 使用半径而非完整内核尺寸:
- 半径 1 = 3x3 内核
- 半径 2 = 5x5 内核
- 半径 3 = 7x7 内核
错误码
| 代码 | 宏 | 含义 |
|---|---|---|
0 | ACL_OK | 成功 |
-1 | ACL_ERR_GENERIC | 未分类错误 |
-2 | ACL_ERR_INVAL | 参数错误(空指针、尺寸为 0、枚举超界) |
-3 | ACL_ERR_NOMEM | 内存不足 / 分配失败 |
-4 | ACL_ERR_NOSUP | 不支持的类型 / 参数组合 |
-5 | ACL_ERR_IO | 文件 / 端口打开或 I/O 失败 |
-1005 | ACL_ERR_NOT_LICENSED | 当前 tier 不含此算子 |
-1006 | ACL_ERR_RESOLUTION_LIMIT | 不符合 Trial 固定尺寸(1920×1280) |
完整错误码定义见 <acl/err.h> 或 API 参考。
下一步
- API 参考 — 完整可调用 API 文档
- OpenCV 迁移指南 — 从 OpenCV 代码迁移
- 性能白皮书 — 详细基准数据