diff --git a/Cpp_example/T02_eigen/CMakeLists.txt b/Cpp_example/T02_eigen/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c08433ddc69da86f1cb8a24e0fed074f4ee0ad45 --- /dev/null +++ b/Cpp_example/T02_eigen/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 3.10) + +project(eigen_test) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 定义项目根目录路径 +set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../..") +message("PROJECT_ROOT_PATH = " ${PROJECT_ROOT_PATH}) + +include("${PROJECT_ROOT_PATH}/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake") + +# 定义 OpenCV SDK 路径 +set(OpenCV_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/opencv-mobile-4.10.0-lockzhiner-vision-module") +set(OpenCV_DIR "${OpenCV_ROOT_PATH}/lib/cmake/opencv4") +find_package(OpenCV REQUIRED) +set(OPENCV_LIBRARIES "${OpenCV_LIBS}") + +# 定义 LockzhinerVisionModule SDK 路径 +set(LockzhinerVisionModule_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk") +set(LockzhinerVisionModule_DIR "${LockzhinerVisionModule_ROOT_PATH}/lib/cmake/lockzhiner_vision_module") +find_package(LockzhinerVisionModule REQUIRED) + + +# 定义 Eigen 路径 +set(Eigen_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk/third_party/eigen") +set(Eigen_DIR "${Eigen_ROOT_PATH}/include/eigen3/") + +message("Eigen_DIR = " ${Eigen_DIR}) + + + +add_executable(eigen_test eigentest.cc) +target_include_directories(eigen_test PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS} ${Eigen_DIR}) +target_link_libraries(eigen_test PRIVATE ${OPENCV_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES} ) +# 告诉 Eigen 使用最大 8 字节对齐(armv7l 平台限制) +target_compile_definitions(eigen_test PRIVATE EIGEN_MAX_ALIGN_BYTES=8) +# 如果你不需要 Eigen 的 SIMD 加速(在嵌入式平台上有时反而会拖慢性能),具体怎样还没有测试,请自行测试 +target_compile_definitions(eigen_test PRIVATE EIGEN_DONT_VECTORIZE) + + +install( + TARGETS eigen_test + RUNTIME DESTINATION . +) \ No newline at end of file diff --git a/Cpp_example/T02_eigen/README.md b/Cpp_example/T02_eigen/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d35b21e281635397abcc8c151547d0d3379714bd --- /dev/null +++ b/Cpp_example/T02_eigen/README.md @@ -0,0 +1,29 @@ +# eigen 测试例程 +## 简介 + +Eigen是一个用于线性运算的C++ 模板库,支持 矩阵和矢量运算,数值分析及其相关的算法。 + + +## 编译项目 + +使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 + +```bash +# 进入Demo所在目录 +cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/Cpp_example/E01_find_number +# 创建编译目录 +rm -rf build && mkdir build && cd build +# 配置交叉编译工具链 +export TOOLCHAIN_ROOT_PATH="/LockzhinerVisionModuleWorkSpace/arm-rockchip830-linux-uclibcgnueabihf" +# 使用cmake配置项目 +cmake .. +# 执行编译项目 +make -j8 && make install +``` + +在执行完上述命令后,会在build目录下生成可执行文件。 +拷贝到视觉模块上运行: +```bash +chmod 777 ./eigen_test +./eigen_test +``` \ No newline at end of file diff --git a/Cpp_example/T02_eigen/eigentest.cc b/Cpp_example/T02_eigen/eigentest.cc new file mode 100644 index 0000000000000000000000000000000000000000..c4f709b758e2efd19ca040ba9a3f4d85ca637d96 --- /dev/null +++ b/Cpp_example/T02_eigen/eigentest.cc @@ -0,0 +1,28 @@ +#include +#include // Eigen 的核心模块 + +int main() { + // 声明两个 3x3 矩阵 + Eigen::Matrix3f matA; + Eigen::Matrix3f matB; + + // 初始化矩阵 A + matA << 1, 2, 3, + 4, 5, 6, + 7, 8, 9; + + // 初始化矩阵 B + matB << 2, 0, 0, + 0, 2, 0, + 0, 0, 2; + + std::cout << "Matrix A:\n" << matA << std::endl; + std::cout << "Matrix B:\n" << matB << std::endl; + + // 矩阵相乘 + Eigen::Matrix3f result = matA * matB; + + std::cout << "Result of A * B:\n" << result << std::endl; + + return 0; +} \ No newline at end of file diff --git a/Cpp_example/T03_opus/CMakeLists.txt b/Cpp_example/T03_opus/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..70034cafd473ce3e03bf81dfb7dca7114255e781 --- /dev/null +++ b/Cpp_example/T03_opus/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.10) + +project(Opus) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# 定义项目根目录路径 +set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../..") +message("PROJECT_ROOT_PATH = " ${PROJECT_ROOT_PATH}) + +include("${PROJECT_ROOT_PATH}/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake") + +# 定义 OpenCV SDK 路径 +set(OpenCV_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/opencv-mobile-4.10.0-lockzhiner-vision-module") +set(OpenCV_DIR "${OpenCV_ROOT_PATH}/lib/cmake/opencv4") +find_package(OpenCV REQUIRED) +set(OPENCV_LIBRARIES "${OpenCV_LIBS}") + +# 定义 LockzhinerVisionModule SDK 路径 +set(LockzhinerVisionModule_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk") +set(LockzhinerVisionModule_DIR "${LockzhinerVisionModule_ROOT_PATH}/lib/cmake/lockzhiner_vision_module") +find_package(LockzhinerVisionModule REQUIRED) + +# 定义 Opus 路径 + +set(Opus_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk/third_party/opus-v1.5.2") +set(Opus_DIR "${Opus_ROOT_PATH}/include/opus/") +set(Opus_LIBRARY_DIR "${Opus_ROOT_PATH}/lib/libopus.a") + + +add_executable(Opus opus.cc) +target_include_directories(Opus PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS} ${Opus_DIR}) +target_link_libraries(Opus PRIVATE ${OPENCV_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES} ${Opus_LIBRARY_DIR}) + + +install( + TARGETS Opus + RUNTIME DESTINATION . +) \ No newline at end of file diff --git a/Cpp_example/T03_opus/README.md b/Cpp_example/T03_opus/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fc67bd456b547cfc810dfe2d53d5b00f475bf9d1 --- /dev/null +++ b/Cpp_example/T03_opus/README.md @@ -0,0 +1,58 @@ +# Opus 测试例程 +## 简介 + +Opus是一款完全开放、免版税、高度通用的音频编解码器。Opus在互联网上的交互式语音和音乐传输方面无与伦比,但也适用于存储和流媒体应用。它被互联网工程任务组(IETF)标准化为 RFC 6716,它结合了Skype的SILK编解码器和Xiph.Org的CELT编解码器的技术。 + +Opus可以处理广泛的音频应用程序,包括IP语音、视频会议、游戏内聊天,甚至远程现场音乐表演。它可以从低比特率的窄带语音扩展到非常高质量的立体声音乐。支持的功能包括: + +比特率从6 kb/s到510 kb/s + +采样率从8kHz(窄带)到48kHz(全频带) + +帧大小从2.5毫秒到60毫秒 + +支持恒定比特率(CBR)和可变比特率(VBR) + +从窄带到全频带的音频带宽 + +支持语音和音乐 + +支持单声道和立体声 + +最多支持255个通道(多流帧) + +可动态调整的比特率、音频带宽和帧大小 + +良好的丢失鲁棒性和丢包隐藏性(PLC) + +浮点和定点实现 + +需要了解更多opus的内容,可以到opus官网:https://www.opus-codec.org 。 + + + +## 编译项目 + +使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 + +```bash +# 进入Demo所在目录 +cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/Cpp_example/E01_find_number +# 创建编译目录 +rm -rf build && mkdir build && cd build +# 配置交叉编译工具链 +export TOOLCHAIN_ROOT_PATH="/LockzhinerVisionModuleWorkSpace/arm-rockchip830-linux-uclibcgnueabihf" +# 使用cmake配置项目 +cmake .. +# 执行编译项目 +make -j8 && make install +``` + +## 下载执行 + +在执行完上述命令后,会在build目录下生成可执行文件。 +拷贝到视觉模块上运行: +```bash +chmod 777 ./Opus +./Opus +``` \ No newline at end of file diff --git a/Cpp_example/T03_opus/opus.cc b/Cpp_example/T03_opus/opus.cc new file mode 100644 index 0000000000000000000000000000000000000000..0e998cfe2da52a2ba446583e1950cd88d028b766 --- /dev/null +++ b/Cpp_example/T03_opus/opus.cc @@ -0,0 +1,145 @@ +#include +#include +#include +extern "C" { +#include +} + +// 配置参数 +#define FRAME_SIZE 960 // 20ms frame at 48kHz +#define SAMPLE_RATE 48000 // Sample rate (Hz) +#define CHANNELS 1 // Mono +#define APPLICATION OPUS_APPLICATION_AUDIO +#define BITRATE 16000 // Bitrate in bps (语音推荐值) + +class OpusTest { +public: + OpusTest() : encoder(nullptr), decoder(nullptr) {} + ~OpusTest(); + + bool init(); + void run(const std::string& inputPath, const std::string& pcmOutputPath); + +private: + OpusEncoder* encoder; + OpusDecoder* decoder; + + void handleErrors(const std::string& message, int errorCode = 0); +}; + +bool OpusTest::init() { + int error; + + // 创建编码器 + encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &error); + if (error != OPUS_OK || !encoder) { + handleErrors("Failed to create encoder", error); + return false; + } + + // 设置比特率 + opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE)); + + // 创建解码器 + decoder = opus_decoder_create(SAMPLE_RATE, CHANNELS, &error); + if (error != OPUS_OK || !decoder) { + handleErrors("Failed to create decoder", error); + return false; + } + + return true; +} + +void OpusTest::handleErrors(const std::string& message, int errorCode) { + std::cerr << message << std::endl; + if (errorCode != 0) { + std::cerr << "Error code: " << opus_strerror(errorCode) << std::endl; + } +} + +void OpusTest::run(const std::string& inputPath, const std::string& pcmOutputPath) { + std::ifstream fin(inputPath, std::ios::binary); + std::ofstream fout(pcmOutputPath, std::ios::binary); + std::ofstream opusOut("output.opus", std::ios::binary); + + if (!fin.is_open() || !fout.is_open() || !opusOut.is_open()) { + std::cerr << "Failed to open input/output file." << std::endl; + return; + } + + opus_int16 pcmBuffer[FRAME_SIZE]; + unsigned char encoded[1024]; // 编码缓冲区 + opus_int16 decoded[FRAME_SIZE]; // 解码缓冲区 + + while (true) { + fin.read(reinterpret_cast(pcmBuffer), sizeof(pcmBuffer)); + std::streamsize readBytes = fin.gcount(); + + if (readBytes <= 0) + break; + + int samples = readBytes / sizeof(opus_int16); + + // 编码 + int encodedSize = opus_encode(encoder, pcmBuffer, samples, encoded, sizeof(encoded)); + if (encodedSize < 0) { + handleErrors("Encoding failed", encodedSize); + continue; + } + + // 写入 Opus 文件 + opusOut.write(reinterpret_cast(encoded), encodedSize); + + // 解码 + int decodedSamples = opus_decode(decoder, encoded, encodedSize, decoded, FRAME_SIZE, 0); + if (decodedSamples < 0) { + handleErrors("Decoding failed", decodedSamples); + continue; + } + + // 写入输出文件 + fout.write(reinterpret_cast(decoded), decodedSamples * sizeof(opus_int16)); + } + + fin.close(); + fout.close(); + opusOut.close(); + + // 统计压缩率 + std::ifstream finStat(inputPath, std::ios::binary); + finStat.seekg(0, std::ios::end); + size_t pcmSize = finStat.tellg(); + + std::ifstream opusStat("output.opus", std::ios::binary); + opusStat.seekg(0, std::ios::end); + size_t opusSize = opusStat.tellg(); + + double compressionRatio = (double)pcmSize / opusSize; + + std::cout << "PCM file size: " << pcmSize << " bytes" << std::endl; + std::cout << "Opus file size: " << opusSize << " bytes" << std::endl; + std::cout << "Compression ratio: " << compressionRatio << "x" << std::endl; +} + +OpusTest::~OpusTest() { + if (encoder) opus_encoder_destroy(encoder); + if (decoder) opus_decoder_destroy(decoder); +} + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return -1; + } + + OpusTest test; + if (!test.init()) { + std::cerr << "Initialization failed." << std::endl; + return -1; + } + + test.run(argv[1], argv[2]); + + std::cout << "Opus encode/decode test completed successfully." << std::endl; + return 0; +} \ No newline at end of file