# algocv **Repository Path**: ninestars_com/algocv ## Basic Information - **Project Name**: algocv - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-07-09 - **Last Updated**: 2024-07-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ```txt AAA lllllll A:::A l:::::l A:::::A l:::::l A:::::::A l:::::l A:::::::::A l::::l ggggggggg ggggg ooooooooooo ccccccccccccccccvvvvvvv vvvvvvv A:::::A:::::A l::::l g:::::::::ggg::::g oo:::::::::::oo cc:::::::::::::::c v:::::v v:::::v A:::::A A:::::A l::::l g:::::::::::::::::go:::::::::::::::o c:::::::::::::::::c v:::::v v:::::v A:::::A A:::::A l::::l g::::::ggggg::::::ggo:::::ooooo:::::oc:::::::cccccc:::::c v:::::v v:::::v A:::::A A:::::A l::::l g:::::g g:::::g o::::o o::::oc::::::c ccccccc v:::::v v:::::v A:::::AAAAAAAAA:::::A l::::l g:::::g g:::::g o::::o o::::oc:::::c v:::::v v:::::v A:::::::::::::::::::::A l::::l g:::::g g:::::g o::::o o::::oc:::::c v:::::v:::::v A:::::AAAAAAAAAAAAA:::::A l::::l g::::::g g:::::g o::::o o::::oc::::::c ccccccc v:::::::::v A:::::A A:::::A l::::::lg:::::::ggggg:::::g o:::::ooooo:::::oc:::::::cccccc:::::c v:::::::v A:::::A A:::::A l::::::l g::::::::::::::::g o:::::::::::::::o c:::::::::::::::::c v:::::v A:::::A A:::::A l::::::l gg::::::::::::::g oo:::::::::::oo cc:::::::::::::::c v:::v AAAAAAA AAAAAAAllllllll gggggggg::::::g ooooooooooo cccccccccccccccc vvv g:::::g gggggg g:::::g g:::::gg gg:::::g g::::::ggg:::::::g gg:::::::::::::g ggg::::::ggg gggggg ``` #
算法框架介绍及使用规范v1.0.0
* [算法框架介绍及使用规范v1.0.0](#算法框架介绍及使用规范v1.0.0) * [基本规范](#基本规范) * [遵守代码风格规范](#遵守代码风格规范) * [注释和文档](#注释和文档) * [代码结构](#代码结构) * [命名规范](#命名规范) * [变量命名](#变量命名) * [函数命名](#函数命名) * [类、结构体命令](#类、结构体命令) * [枚举类型命名](#枚举类型命名) * [宏命名](#宏命名) * [命名空间](#命名空间) * [其他](#其他) * [合理组织文件和目录](#合理组织文件和目录) * [使用模块化和封装](#使用模块化和封装) * [明确错误处理](#明确错误处理) * [优化循环和逻辑](#优化循环和逻辑) * [版本控制](#版本控制) * [单元测试和代码审查](#单元测试和代码审查) * [算法工程](#算法工程) * [目录结构介绍](#目录结构介绍) * [代码编译](#代码编译) * [开发板编译](#开发板编译) * [本机交叉编译](#本机交叉编译) * [本机直接编译](#本机直接编译) * [Docker编译](#docker编译) * [代码框架](#代码框架) * [消息类图](#消息类图) * [日志类图](#日志类图) * [代理类图](#代理类图) * [配置文件](#配置文件) * [开发插件](#开发插件) * [算法输出](#算法输出) * [Demo例程的构建](#demo例程的构建) * [编译Demo](#编译demo) * [输出内容介绍](#输出内容介绍) ## 基本规范 ### 遵守代码风格规范 在C++编程中,遵守代码风格规范非常重要,可以让代码更具可读性和可维护性。 #### 注释和文档 帮助他人快速理解代码的功能和工作方式 - 文件注释 ```cpp /** * @file ninestars.cpp * @brief This is a demo brief */ ``` - 函数注释 ```cpp /** * @brief Returns the maximum between two integers * * @param a An integer value * @param b Another integer value * @return The larger of the two integer values. */ int max(int a, int b) { return (a > b) ? a : b; } - 类声明注释 ```cpp /** * @class Caculator * @brief This is a caculator class defination * */ class Caculator : public Object { public: Caculator(int arg1, int arg2); ~Caculator(); int max(int a, int b); private: int mArg1; int mArg2; }; ``` #### 代码结构 保持代码的结构整洁, - 缩进和行长: 设置tab的宽度为4, 单行代码的长度应在80到120个字符以内, 运算符和逗号后添加空格。 ```cpp int sum = a + b; // Add spaces around the operator for (int i = 0; i < n; ++i) { // Add a space after the semicolons char *long_string = "This is a very long string that " "needs to be broken into multiple " "lines for better readability."; } ``` - 函数参数列表: 参数较多时,适当的换行和缩进可以提高代码可读性, 同时建议一个函数不要传递太多参数。 ```cpp void doSomething( int parameter_long_name_1, int parameter_long_name_2, const std::string& parameter_long_name_3, const std::vector& parameter_long_name_4) { } ``` - 代码块括号: 即使是单条语句的控制快,**建议**也使用括号,避免潜藏的错误。 ```cpp if (condition) { donSomething(); } ``` - 数据封装: 使用类的公有方法操作类中的私有成员变量,不要直接去访问它们。 ```cpp class BankAccount { public: void deposit(double amount) { if (amount > 0) { mBalance += amount; } } private: double mBalance = 0; }; ``` - 避免使用魔术数字: 硬编码的数字应定义为常量或宏,且名字具有一定可读性。 ```cpp const int MaxBufferSize = 512; char buffer[MaxBufferSize]; ``` - 避免使用全局变量 ### 命名规范 #### 变量命名 需清晰反映用途,全局变量以g开头,静态变量以s开头,常量变量以k开头,类成员变量以m开头, 采用骆驼峰命名且首字母**小**写。 如果既是静态或者常量,又是全局变量,以g开头。 > ```cpp > class Caculator : public Object { > public: > Caculator(int weightX, int weightX): mWeightX(weightX), mWeightY(weightX) {} > ~Caculator() {} > > int calculateWeightedSum(int x, int y) { > return mWeightX * x + mWeightY *y; > } > > private: > int mWeightX; > int mWeightY; > }; > > const int kFixWeight = 0.321; > const Caculator* gCaculator = nullptr; ``` #### 函数命名 需清晰反映函数功能,采用骆驼峰规则命名且首字母**小**写。 > ```cpp > int calculateMaximum(int a, int b) > { > return (a > b) ? a : b; > } > ``` #### 类、结构体命令 采用骆驼峰命名法,且首字母**大**写 > ```cpp > class StudentInfo { > //... > }; > ``` #### 枚举类型命名 采用骆驼峰,首字母小写**e** (建议) > ```cpp > enum State { > eAlgoInit = 0, > eAlgoDCPositioning = 1, > eAlgoNull, > }; > ``` #### 宏命名 需清晰反映用途,字符全部大些,单词间可以使用**\_**连接 > ```cpp > #define CAMERA_D_ALIGNMENT 100 // double camera alignment > #define CAMERA_S_AUTOFOCUS 101 // single camera autofocus > ``` #### 命名空间 命名空间的名字应该能够反映其封装的代码的功能。避免在头文件中直接使用using namespace将整个命名空间引入。 > ```cpp > // Good practice: descriptive and hierarchical namespace > namespace ninestars { > namespace math { > class Vector { /* ... */ }; > } > } > > // Using declarations to simplify usage in .cpp files > using ninestars::math::Vector; > > // Bad practice: overuse of using directive in header file > // This can lead to naming collisions and is not recommended. > using namespace ninestars; > ``` ### 其他 #### 合理组织文件和目录 1. 将相关的代码文件组织在同一目录下。 2. 使用清晰、描述性的文件名和目录名。 #### 使用模块化和封装 1. 将代码分割成小的、可重用的模块。 2. 封装模块内部的实现细节,仅暴露必要的接口。 #### 明确错误处理 1. 在代码中明确地处理错误情况。 2. 使用异常处理、错误码或是状态标志等机制来管理错误。 #### 优化循环和逻辑 1. 避免不必要的循环和递归调用。 2. 优化条件判断,减少循环迭代次数。 #### 版本控制 1. 使用版本控制系统,如Git,来管理代码的版本。 2. 遵循良好的提交实践,如使用清晰的提交消息,以及合理地分割代码改动。 #### 单元测试和代码审查 1. 编写接口/功能函数等单元测试,确保代码功能的正确性和稳定性。 2. 定期组织代码审查、评估代码质量。 ## 算法工程 ### 目录结构介绍 ``` algocv │ ├── assets ────────────────────► 调试: 算法用到的资源,比如测试图片,测试页面。 │   ├── images │   └── www ├── cmake ────────────────────► 构建: 项目的配置,根据选项或者平台属性,选择合适的交叉编译链和文件系统。 │   ├── platform │   │   ├── RK3566 │   │   └── RK3588 │   └── projects │   ├── biometric_instrument │   ├── corneal_endothelium │   └── fundus_camera ├── config ────────────┐ │   └── etc └───────► 调试: 工具类相关的配置,比如nginx、rsync等。 │   └── nginx │   └── conf.d ├── docker ────────────────────► 环境: 创建目标平台镜像环境的配置。 │   └── aarch64 ├── docs ───────────────┐ │   ├── framework └────► 文档: markdown、doc、notebook等。 │   └── codeguide ───────────┐ │   └── notebooks └────► 文档:接口使用、项目需求样例等。 │   └── fundus_camera ├── examples ────────────────────► 调试: 具有一定功能的测试样例。 │   └── motor_control ├── externals ───────────────┐ │   ├── platform └────► 构建: (git)子模块,存放构建项目依赖的交叉编译链、文件系统、第三方库等。 │   │   └── RK3588 │   ├── thirdparts │   │   └── json │   │   └── nlohmann ┌───► 调试: 潜入到算法库,具有一定功能的插件开发,比如:控制电机、设置日志级别等。 │   └── toolchain │ ├── plugins ────────────────┘ │   ├── http_server │   └── stream_server ├── scripts ────────────────────► 构建: cmake 配置项目时调用的脚本、其他启动脚本等。 ├── src │   ├── app ────────────────────► 算法: 使用算法库完成具体的应用(暂时无)。 │   │   └── Qt │   └── lib ────────────────────► 算法: 算法框架、算法核心 │   ├── core ═══════════════╗ │   │   ├── camera ╠════════► 相机相关 │   │   ├── fpga ╠════════► FPGA相关 │   │   ├── handler ╠════════► 与软件应用对应,处理软件发过来的消息命令的处理程序。 │   │   ├── helper ╠════════► 通用辅助类 │   │   ├── measure ╠════════► 测量类算法 │   │   ├── motor ╠════════► 电机相关,如移动步长计算。 │   │   └── xpu ╠════════► 深度学习推理算法。 │   │   ├── jetson │   │   └── rknn │   ├── logger ══════════════╗ │   ├── osmsg ║ 算法: 基础框架(消息系统、设置、日志系统) │   ├── setting ║ │   └── utils ══════════════╝ ├── tests ──────────────────────► 调试: 接口、函数、类等单元测试 │   ├── camera │   ├── cvmsg │   ├── handler │   ├── helper │   ├── motor │   ├── qtlog │   ├── setting │   └── xpu └── tools ──────────────────────► 工具: 可以加快开发、问题定位的任何工具类,如:日志控制、标定等。 ``` ### 代码编译 假设`ALGOCV_TOP_DIR`是算法工程的TOP目录 #### 开发板编译 将代码直接`git clone`到开发板上进行开发。 - 优点: 能够保证运行环境一致性。 - 缺点: 需要依赖设备开发,代码放到设备上不安全,涉及到核心代码外泄等。 构建编译步骤: > ```sh > cd ${ALGOCV_TOP_DIR} > mkdir build > cd build > ccmake ../ # c - c - e - c - g > make -j > ``` ![](assets/images/build/ccmake-option.png) #### 本机交叉编译 将代码直接git clone到本机电脑上(本机要求是Linux,构建脚本是linux写的) 交叉编译之后,需要推送开发板上执行,可以通过执行下面的命令自己推送: 1. `make remote_so` 将编译后的库推送到开发板, 需要配置`${ALGOCV_TOP_DIR}/.so-sync`中的开发板地址 2. `make remote_package` 如果代码修改了对外的几个头文件(7个), 需要配置`${ALGOCV_TOP_DIR}/.dev-sync` - 优点:开发调试速度快,根据爱好选择自己熟悉的代码编辑器。 - 缺点:sysroot文件系统需要根据对应板子(如kr3588)制作压缩包。(只需一次) ![](assets/images/build/ccmake-cross.png) #### 本机直接编译 通过配置选项关闭XPU,可以编译出amd64库,结合测试单元,快速验证自己的算法或者程序。 - 优点:同上,本地可执行,非常适合本地快速验证算法接口。 - 缺点:不支持编译XPU, 与深度模型推理的算法代码不会编译。 ![](assets/images/build/ccmake-local.png) #### 嵌入式Docker编译 首先使用`${ALGOCV_TOP_DIR}/scripts/build_aarch64_docker.sh`建立一个aarch64嵌入式进行, 需要传入正确的文件系统 比如rk3588, 文件系统在`${ALGOCV_TOP_DIR}/externals/platform`中可以找到, 如果文件系统与开发板一致时,可保证环境一致性。 构建之后,需要启动容器执行`${ALGOCV_TOP_DIR}/scripts/start_aarch64_docker.sh`。 - 优点: 编译程序可以在容器内执行,无需推送到开发板, 代码可在容器外开发,选择喜爱的代码编辑器。 - 缺点: 构建的镜像暂用大量磁盘空间。 ![](assets/images/build/ccmake-docker.png) ### 代码框架 #### 消息类图 **GO**➡️ [docs/framework/message.md](docs/framework/message.md) 算法与软件异步交互,以及算法模块之间交互的核心组件。算法初始化时,启动一个主消息线程,用于接收和分发消息。 #### 日志类图 **GO**➡️ [docs/framework/log.md](docs/framework/log.md) 建议: 如果某个算法模块比较繁重,需要实现对应的LOG模块, 如Handler模块 > ``` > extern int gHandlerModuleLevel; > > #define HANDLER_LOGE(args...) _LOGE(gHandlerModuleLevel, args) > #define HANDLER_LOGW(args...) _LOGW(gHandlerModuleLevel, args) > #define HANDLER_LOGD(args...) _LOGD(gHandlerModuleLevel, args) > #define HANDLER_LOGI(args...) _LOGI(gHandlerModuleLevel, args) > ``` > ```cpp > int gHandlerModuleLevel = LOG_LEVEL_DEBUG; > > static LogModule HandlerLogModule("handler", gHandlerModuleLevel); > ``` 好处: 每个模块单独设置日志级别, 可以通过配置文件,或者开启Plugin功能,动态设置各个框架模块的日志级别。 #### 代理类图 **GO** ➡️ [docs/framework/useme.md](docs/framework/useme.md) QAlgocvAgent 专门为algocv异步输出的图片数据,需要UI显示,可以交给QAlgocvAgent将数据发给UI主线程。 ### 配置文件 减少硬编码 TODO ### 开发插件 辅助algocv调试 TODO ## 算法输出 以[相机对位](examples/Qt/camera_align/)的算法模块为例,介绍本地开发调试及算法最终的输出(给软件部门使用)。 ### Demo例程的构建 编写构建文件[CMakeLists.txt](examples/Qt/camera_align/CMakeLists.txt), 该文件分为两部分: ```cmake if(DEFINED APP_SOURCE_DIRECTORY) # 1. 随algocv项目构建一起编译,并导出算法需要输出的文件 set(DEMO_NAME camera_align) set(SOURCE_FILES ${APP_SOURCE_DIRECTORY}/Qt/QAlgocvAgent.cpp main.cpp ) ... install(FILES ${SOURCE_FILES} DESTINATION ${DEMO_NAME}/src) install(FILES ${INSTALL_HEADER_FILES} DESTINATION ${DEMO_NAME}/src) install(FILES ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt DESTINATION ${DEMO_NAME}) install(FILES ${DOCS_SOURCE_DIRECTORY}/codeguide/app/camera_align.md DESTINATION ${DEMO_NAME}/docs) configure_file(${EXAMPLES_SOURCE_DIRECTORY}/run_it.sh.in ${CMAKE_INSTALL_PREFIX}/${DEMO_NAME}/run_it.sh @ONLY) execute_process(COMMAND chmod +x ${CMAKE_INSTALL_PREFIX}/${DEMO_NAME}/run_it.sh) else() # 2. 基于算法输出的文件进行独立地项目构建 (方便软件开发人员直接构建) cmake_minimum_required(VERSION 3.10) project(example_camera_align) ... add_executable(camera_align ${SOURCE_FILES}) set_target_properties(camera_align PROPERTIES LINK_FLAGS "-Wl,--as-needed") target_link_directories(camera_align PRIVATE ${CMAKE_CURRENT_LIST_DIR}/lib) target_link_libraries(camera_align algocv Qt5::Core Qt5::Widgets ${OpenCV_LIBS}) endif() ``` ### 编译Demo 可以选择`交叉编译`、`Docker容器内编译`、`开发板上编译`等几种方式(上面的介绍)。这里以`容器`的方式编译Algocv算法 1. 启动/进去容器: [./scripts/start_aarch64_docker.sh](scripts/start_aarch64_docker.sh) ![](assets/images/build/start_aarch64_container.png) 2. 选择算法交付的项目以及Demo配置 ![](assets/images/build/demo_select_options.png) 3. package输出 ```sh make -j2 make install # 生成package目录 ``` 4. 验证Demo ```sh cd package/corneal_endothelium/camera_align ./run_it.sh # 1. 构建Demo --> 2. 编译 --> 3. 运行 (如果脚本输出正常,则可打包并发给软件开发人员 ``` ### 输出内容介绍 ``` ┌─────────────► 将这个目录打包发给“使用者” │ package/ │ ├── corneal_endothelium ────────────────► cmake编译时选择的项目 │   └── camera_align ────────────────► cmake编译时选择的Demo模块 │   ├── algocv_conf.ini.in ────────────────► 算法配置文件模板,构建时自动替换,可配置 │   ├── CMakeLists.txt │   ├── docs ──────────────────────────────────────────► 提供简单的介绍 │   │   └── camera_align.md ┌──────────────────────────► 使用者只需要引入algocv_api.h头文件即可 │   ├── include │ ─────────┐ │   │   ├── algocv_api.h ────┘ │ │   │   ├── AlgocvHandler.h │ │   │   ├── Message.h ├───────► 算法提供出的外部头文件 │   │   ├── MessageHandler.h │ │   │   ├── MessageTypes.h │ │   │   ├── Object.h │ │   │   └── PayloadTypes.h ─────────┘ │   ├── lib │   │   └── libalgocv.so ───────────────────────────────► 输出的算法库 │   ├── run_it.sh ─────────────────────────────────────────► 编译Demo的脚本, 直接执行,可输出结果 │   └── src ──────────┐ │   ├── AlgocvQtAgentDemo.cpp ├──────► 测试Demo, 使用者能够快速适用算法模块 │   ├── AlgocvQtAgentDemo.h │ │   └── main.cpp ──────────┘ └── run_camera_align.sh ```