diff --git a/Cpp_example/C08_Apriltag/CMakeLists.txt b/Cpp_example/C08_Apriltag/CMakeLists.txt index bace036d46e80a61e62df7b123e1a10ae6c787d7..9e43592d901c5377ba06706726a570d6c58c38a6 100644 --- a/Cpp_example/C08_Apriltag/CMakeLists.txt +++ b/Cpp_example/C08_Apriltag/CMakeLists.txt @@ -25,18 +25,31 @@ find_library(APRILTAG_LIB NAMES apriltag PATHS ${APRILTAG_LIB_DIR} REQUIRED) # include_directories("${PROJECT_ROOT_PATH}/third_party/eigen-master/") include_directories("${PROJECT_ROOT_PATH}/third_party/apriltag-with-pose-estimation-master") -# 设置 Eigen 路径 -set(EIGEN_ROOT_DIR "${PROJECT_ROOT_PATH}/third_party/eigen-master") +# 定义 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/") # 添加头文件搜索路径 include_directories( - ${EIGEN_ROOT_DIR} + ${Eigen_DIR} ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR} ) + # 创建可执行文件 add_executable(Test_Apriltag Apriltag.cc) +# 告诉 Eigen 使用最大 8 字节对齐(armv7l 平台限制) +target_compile_definitions(Test_Apriltag PRIVATE EIGEN_MAX_ALIGN_BYTES=8) +add_definitions(-DEIGEN_MAX_ALIGN_BYTES=8) + +# 消除 Eigen 的 alignment 警告 +target_compile_definitions(Test_Apriltag PRIVATE EIGEN_MAX_ALIGN_BYTES=8) + +# 可选:关闭 attributes 警告 +target_compile_options(Test_Apriltag PRIVATE -Wno-attributes) + + # 链接库文件 target_link_libraries(Test_Apriltag diff --git a/Cpp_example/D13_target_tracking/README.md b/Cpp_example/D13_target_tracking/README.md index 462ebbcff6c9cbc218e67b5e0eb8f5f15fddf73e..96f01ad1be1cbe893cec01a202058208d6ee111c 100755 --- a/Cpp_example/D13_target_tracking/README.md +++ b/Cpp_example/D13_target_tracking/README.md @@ -1,4 +1,4 @@ -# 多目标跟踪我能当 +# 多目标跟踪 本文档介绍了如何使用 lockzhiner_vision_module 库结合卡尔曼滤波和匈牙利算法实现多目标跟踪系统。 diff --git a/Cpp_example/T01_jsoncpp/CMakeLists.txt b/Cpp_example/T01_jsoncpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..70c426e28c91a9121883ffd653dc44b7d33ebb5d --- /dev/null +++ b/Cpp_example/T01_jsoncpp/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.10) + +project(jsontest) + +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) + + +# 定义 jsoncpp 路径 +set(JSONCPP_ROOT_PATH "${PROJECT_ROOT_PATH}/third_party/lockzhiner_vision_module_sdk/third_party/jsoncpp") +set(JSONCPP_INCLUDE_DIRS "${JSONCPP_ROOT_PATH}/include/") +set(JSONCPP_LIBRARIES "${JSONCPP_ROOT_PATH}/lib/libjsoncpp.a") + +message("JSONCPP_INCLUDE_DIRS = " ${JSONCPP_INCLUDE_DIRS}) + +add_executable(jsontest jsontest.cc) +target_include_directories(jsontest PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS} ${JSONCPP_INCLUDE_DIRS}) +target_link_libraries(jsontest PRIVATE ${OPENCV_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES} ${JSONCPP_LIBRARIES}) + +install( + TARGETS jsontest + RUNTIME DESTINATION . +) \ No newline at end of file diff --git a/Cpp_example/T01_jsoncpp/README.md b/Cpp_example/T01_jsoncpp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..85720038c427463dcae954cde1d2bf3dcdabe8dd --- /dev/null +++ b/Cpp_example/T01_jsoncpp/README.md @@ -0,0 +1,34 @@ +# jsoncpp 测试例程 +## 简介 + +JSON 是一种轻量级数据交换格式。它可以表示数据、字符串、有序的值序列以及名称/值对的集合。 + +jsoncpp 是一个 C++ 库,允许操作 JSON 值,包括字符串之间的序列化和反序列化。它还可以在反序列化/序列化步骤中保留现有注释,使其成为存储用户输入文件的方便格式。 + +JsonCpp 目前在 github 上托管。为方便使用将改项目继承到 SDk 中。 + +官方网址:https://github.com/open-source-parsers/jsoncpp + +## 编译项目 + +使用 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 ./jsontest +./jsontest + 具体的任务 +``` \ No newline at end of file diff --git a/Cpp_example/T01_jsoncpp/images/E02.png b/Cpp_example/T01_jsoncpp/images/E02.png new file mode 100644 index 0000000000000000000000000000000000000000..b71a6c4ffc10b2dfc86fc22ca76542967818bf78 Binary files /dev/null and b/Cpp_example/T01_jsoncpp/images/E02.png differ diff --git a/Cpp_example/T01_jsoncpp/jsontest.cc b/Cpp_example/T01_jsoncpp/jsontest.cc new file mode 100644 index 0000000000000000000000000000000000000000..31db4927ae56acf746ff9c82b32b7f8c5c15c939 --- /dev/null +++ b/Cpp_example/T01_jsoncpp/jsontest.cc @@ -0,0 +1,154 @@ +#include "json/json.h" +#include +#include +#include +#include + +// 打印帮助信息 +void printUsage(const std::string& progName) { + std::cout << "Usage: " << progName << " [option]\n"; + std::cout << "Options:\n"; + std::cout << " write - Write sample JSON to stdout\n"; + std::cout << " writestr - Write JSON to string\n"; + std::cout << " readstr - Read JSON from string\n"; + std::cout << " writefile - Write JSON to file (example.json)\n"; + std::cout << " readfile - Read JSON from file (example.json)\n"; +} + +// 将 Json::Value 转换为字符串输出 +std::string writeToJsonString(const Json::Value& root) { + Json::StreamWriterBuilder builder; + std::ostringstream oss; + std::unique_ptr writer(builder.newStreamWriter()); + writer->write(root, &oss); + return oss.str(); +} + +// 构建一个测试用的 JSON 对象 +Json::Value createSampleJson() { + Json::Value root; + root["Name"] = "robin"; + root["Age"] = 20; + + Json::Value hobbies(Json::arrayValue); + hobbies.append("reading"); + hobbies.append("coding"); + hobbies.append("hiking"); + + root["Hobbies"] = hobbies; + + Json::Value address; + address["City"] = "Beijing"; + address["ZipCode"] = "100000"; + root["Address"] = address; + + return root; +} + +// 从字符串解析 JSON +bool parseJsonFromString(const std::string& jsonStr, Json::Value& root) { + Json::CharReaderBuilder builder; + std::string errs; + std::istringstream jsonStream(jsonStr); + bool ok = Json::parseFromStream(builder, jsonStream, &root, nullptr); + if (!ok) { + std::cerr << "Failed to parse JSON string." << std::endl; + return false; + } + return true; +} + +// 写入 JSON 到文件 +bool writeJsonToFile(const std::string& filename, const Json::Value& root) { + std::ofstream ofs(filename); + if (!ofs.is_open()) { + std::cerr << "Failed to open file for writing: " << filename << std::endl; + return false; + } + + Json::StreamWriterBuilder builder; + std::unique_ptr writer(builder.newStreamWriter()); + writer->write(root, &ofs); + ofs.close(); + return true; +} + +// 从文件读取 JSON +bool readJsonFromFile(const std::string& filename, Json::Value& root) { + std::ifstream ifs(filename); + if (!ifs.is_open()) { + std::cerr << "Failed to open file for reading: " << filename << std::endl; + return false; + } + + // 使用 JsonCpp 提供的 parseFromStream 方法更简洁 + Json::CharReaderBuilder builder; + std::string errs; + bool ok = Json::parseFromStream(builder, ifs, &root, nullptr); + ifs.close(); + + if (!ok) { + std::cerr << "Failed to parse JSON from file." << std::endl; + return false; + } + + return true; +} + +int main(int argc, char* argv[]) { + std::string operation = "write"; // 默认操作 + if (argc > 1) { + operation = argv[1]; + } else { + printUsage(argv[0]); + return EXIT_FAILURE; + } + + if (operation == "write") { + // 直接写入到 stdout + Json::Value root = createSampleJson(); + std::cout << "=== Writing JSON to stdout ===\n"; + std::cout << writeToJsonString(root) << std::endl; + + } else if (operation == "writestr") { + // 写入 JSON 到字符串 + Json::Value root = createSampleJson(); + std::string jsonStr = writeToJsonString(root); + std::cout << "=== JSON as string ===\n" << jsonStr << std::endl; + + } else if (operation == "readstr") { + // 测试从字符串解析 JSON + std::string jsonStr = R"({"Name":"jack","Age":30,"Hobbies":["music","travel"],"Address":{"City":"Shanghai"}})"; + Json::Value root; + if (parseJsonFromString(jsonStr, root)) { + std::cout << "=== Parsed JSON from string ===\n"; + std::cout << "Name: " << root["Name"].asString() << "\n"; + std::cout << "Age: " << root["Age"].asInt() << "\n"; + std::cout << "First Hobby: " << root["Hobbies"][0].asString() << "\n"; + std::cout << "City: " << root["Address"]["City"].asString() << "\n"; + } + + } else if (operation == "writefile") { + // 写入 JSON 到文件 + Json::Value root = createSampleJson(); + if (writeJsonToFile("example.json", root)) { + std::cout << "JSON written to example.json\n"; + } + + } else if (operation == "readfile") { + // 从文件中读取并解析 JSON + Json::Value root; + if (readJsonFromFile("example.json", root)) { + std::cout << "=== Read JSON from file ===\n"; + std::cout << "Name: " << root["Name"].asString() << "\n"; + std::cout << "Age: " << root["Age"].asInt() << "\n"; + std::cout << "City: " << root["Address"]["City"].asString() << "\n"; + } + + } else { + printUsage(argv[0]); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file 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 diff --git a/F&Q/faq.md b/F&Q/faq.md new file mode 100644 index 0000000000000000000000000000000000000000..8d2e919818711df2a43e1ad3409a4ffa147685b7 --- /dev/null +++ b/F&Q/faq.md @@ -0,0 +1,90 @@ +# 凌智视觉模块F&Q文档 + +## 环境搭建 + +1、环境拉取 + +```markdown +git clone https://gitee.com/LockzhinerAI/arm-rockchip830-linux-uclibcgnueabihf.git +Cloning into 'arm-rockchip830-linux-uclibcgnueabihf'...fatal: unable to access 'https://gitee.com/LockzhinerAI/arm-rockchip830-linux-uclibcgnueabihf.git/': could not resolvehost: gitee.com +``` + +如果出现以上问题,将对应的**文件夹删除**,然后重新执行git clone 命令 + +2、环境已经存在 + +```bash +git clone https://gitee.com/LockzhinerAI/arm-rockchip830-linux-uclibcgnueabihf.gitfatal: destination path 'arm-rockchip830-linux-uclibcgnueabihf' already exists and is not an empty directory. +``` + +出现该提示,表示文件已经存在,如果需要重新拉去,需要将改文件夹删除 + +3、三方依赖库不全 + +![](./images/missingfile.jpg) + +如果出现出现该情况,请根据教程进行重新拉取三方库 + +## 设备使用 + +1、摄像头的基本使用 + +本模块在使用时,需要配合程序使用,如果**直接**连接摄像头后,想要直接打开可视化软件是不可行的 + +2、代理问题 + +如果出现该提示 + +![](./images/agent.jpg) + +请关闭本机的代理软件(如校园网的vpn等) + +3、发热问题 + +发热的时候或者有其他硬件故障的话,请联系我们,不要尝试自己维修。摄像头发热是正常现象,最高温度会有60左右,摸起来会略微烫手 + +4、远程支持 + +如果需要远程支持,请下载最新版的 **todesk** ,同时确保网络畅通 + +5、IP 配置 + +**gitee** 上面的文档虽然任然写着需要配置文档,但目前的镜像不需要进行配置**IP**,可以直接连接使用,不需要配置 IP, 留有 **IP** 设置的原因是以防万一,避免不同设备的兼容性问题。 + +6、VScode 连接 Docker + +在完成基础环境搭建后,如果说需要进行 **c++** 开发,推荐使用vscode 连接 docker, **VScode** docker 插件安装方式: + +打开 vscode 的拓展可以使用快捷键(Ctrl+Shift+X)下载 Docker 、Remote - SSH 、Remote - SSH: Editing Config 、Remote Explorer 等插件 + +启动容器 + +![](./images/docker1.jpg) + +进入容器 + +![](./images/docker2.jpg) + +切换工作目录 + +![](./images/config.jpg) + +6、进程查看 + +进程查看工具可以使用 top / htop + +在使用该工具时颜色可能会有变化,属于正常现象 + +7、自启动设置 + +如果有设置自启动脚本并使用摄像头,在终端想要使用摄像头时需要将原有进程杀死。 + +## 程序编译 + +1、cpp 程序编译 + +```bash +自己写的文件保存了,然后在自己文件这一栏右键打开终端然后生成可执行文件,但是它一直是生成的标准历程里的可执行文件 +``` + +请根据**自定义文件名**修改cmak,如果不知到如何修改的话,可以拷贝一个例程,不修改文件名,只修改里面的内容(同时如果需要视觉功能最好使用E或D例程进行替换可以减少写cmake的麻烦) \ No newline at end of file diff --git a/F&Q/images/agent.jpg b/F&Q/images/agent.jpg new file mode 100644 index 0000000000000000000000000000000000000000..242d9364d8e65d3cec496ce1108de72a7f781852 Binary files /dev/null and b/F&Q/images/agent.jpg differ diff --git a/F&Q/images/config.jpg b/F&Q/images/config.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfe27063b90e7b64f5bf6d37cc8adfb11340a15a Binary files /dev/null and b/F&Q/images/config.jpg differ diff --git a/F&Q/images/docker1.jpg b/F&Q/images/docker1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4ca097767437b754bde189a29c576af85e82fee7 Binary files /dev/null and b/F&Q/images/docker1.jpg differ diff --git a/F&Q/images/docker2.jpg b/F&Q/images/docker2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cf9a4b08eff4ab4286341a42889df0231254ae12 Binary files /dev/null and b/F&Q/images/docker2.jpg differ diff --git a/F&Q/images/missingfile.jpg b/F&Q/images/missingfile.jpg new file mode 100644 index 0000000000000000000000000000000000000000..404f12e9c526e080d5c5452366630ae8a516f3fd Binary files /dev/null and b/F&Q/images/missingfile.jpg differ diff --git a/README.md b/README.md index 81dccb341ab0bca255203b82e62f1cb1082efcc3..d2fdd63629d385c643fc94b13af846941db87d30 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,10 @@ * [凌智视觉模块 C++ 开发环境搭建指南](./docs/introductory_tutorial/cpp_development_environment.md) * [基于 C++ 编写 Hello World 程序](./example/hello_world) --> +## 💡 F&Q + +在使用过程中,如果遇到问题,请先查看 [FAQ](./F&Q/faq.md),如果问题没有解决,请提 issue。 + ## 💡 自启动设置 [自启动脚本设置](./docs/自启动设置.md),设置完后可以说使得视觉模块脱机运行 diff --git a/docs/introductory_tutorial/cpp_development_environment.md b/docs/introductory_tutorial/cpp_development_environment.md index aebb9c69746fb92994ad693aa93d5810fd3f5604..2f1f11d59e8b4cfbe0ac0d9b429dba56f652e7c5 100644 --- a/docs/introductory_tutorial/cpp_development_environment.md +++ b/docs/introductory_tutorial/cpp_development_environment.md @@ -248,9 +248,19 @@ rm -rf apriltag-with-pose-estimation-master.zip wget https://gitee.com/LockzhinerAI/apriltag-with-pose-estimation-master/releases/download/apriltag-with-pose-estimation-master/apriltag-with-pose-estimation-master.zip unzip -qo apriltag-with-pose-estimation-master.zip -d third_party # 下载 eigen -rm -rf eigen-master.zip -wget https://gitee.com/LockzhinerAI/eigen-master/releases/download/v0.1/eigen-master.zip -unzip -qo eigen-master.zip -d third_party +rm -rf eigen.zip +wget https://gitee.com/LockzhinerAI/eigen-master/releases/download/v0.1/eigen.zip +unzip -qo eigen.zip -d third_party + +# 下载 jsoncpp +rm -rf jsoncpp.zip +wget https://gitee.com/LockzhinerAI/jsoncpp/releases/download/v0.1/jsoncpp.zip +unzip -qo jsoncpp.zip -d third_party + +# 下载 opus +rm -rf opus-v1.5.2.zip +wget https://gitee.com/LockzhinerAI/opus/releases/download/v0.1/opus-v1.5.2.zip +unzip -qo opus-v1.5.2.zip -d third_party ``` ### 6.5 下载/更新 LockzhinerVisionModule SDK diff --git a/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake b/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake index 4442bf2181af6784b93cbe9bcf14756f0245d608..ab1ecd61e240522a74645e4df02da08ab75d5b46 100644 --- a/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake +++ b/toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake @@ -22,3 +22,4 @@ set(CMAKE_CXX_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=neon") # cache flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-psabi") \ No newline at end of file