diff --git a/.gitignore b/.gitignore index f488f24efa786fc0e98c8fed69fd8a29d2c5ad42..b88c52a90ca5a96f1f479e79691e4f7bd731c4cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ -# Build Temp +# IDE +.idea +.vscode + +# System +.DS_Store +# Build Temp build lockzhiner_vision_module_sdk* opencv-mobile-4.10.0-lockzhiner-vision-module* -.vscode Temp -.DS_Store diff --git a/README.md b/README.md index 4c39c5ee513cc71c63973c3c31b8c8eb78c5b540..f27b55db21343cf58c96c5ea87f4cc20de94c8f1 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,34 @@

凌智视觉模块(Lockzhiner Vision Module)

-凌智视觉模块(Lockzhiner Vision Module) 是福州市凌睿智捷电子有限公司倾力打造的一款高集成度人工智能视觉模块,专为边端人工智能和机器视觉应用而设计,其特色包括: +

+ + + + + + + + + + + + +

+ +

+ + + +

+ +凌智视觉模块(Lockzhiner Vision Module) 是福州市凌睿智捷电子有限公司联合百度 PaddlePaddle 倾力打造的一款高集成度人工智能视觉模块,专为边缘端人工智能和机器视觉应用而设计,其特色包括: * 卓越的计算能力:Lockzhiner Vision Module 搭载单核 ARM Cortex-A7 处理器,并集成了 NEON 和 FPU,以更出色地处理 SIMD 和浮点计算。同时,该模块支持 Int8 量化,内置 0.5 TOPs 的 NPU,足以应对绝大多数的视觉应用场景。 -* 广泛的开源适配:Lockzhiner Vision Module 与 PaddleClas、PaddleDetection、PaddleSeg、PaddleOCR 等基于 Paddle 框架的视觉场景库完美适配,并内置了一键启动脚本。配合 AIStudio,用户可以实现一键训练、一键部署,从而极大地减轻了部署负担。 +* 广泛的开源适配:Lockzhiner Vision Module 与 PaddleClas、PaddleDetection、PaddleSeg、PaddleOCR 等基于 Paddle 框架的视觉场景库完美适配。配合 AIStudio,用户可以实现一键训练、一键部署,从而极大地减轻了部署负担。 -## 🔄 最新日志 +> 更详细的参数请参考 [凌智视觉模块设备详细参数文档](./docs/device_parameters.md) +## 🔄 最新日志 ## 💡 入门学习教程 @@ -14,7 +36,9 @@ * [凌智视觉模块烧录镜像指南](./docs/introductory_tutorial/burn_image.md) * [凌智视觉模块连接设备指南](./docs/introductory_tutorial/connect_device_using_ssh.md) +* [凌智视觉模块 Python 开发环境搭建指南](./docs/introductory_tutorial/python_development_environment.md) + ## 🔌 外设控制教程 @@ -32,26 +57,26 @@ Lockzhiner Vision Module 拥有丰富的 IO 接口,其接口图片如下图所 为了帮助你快速上手教程,我们提供了一系列的外设控制例程,你可以点击链接快速学习 -* [凌智视觉模块串口使用指南](./example/periphery/usart/README.md) -* [凌智视觉模块 ADC 使用指南](./example/periphery/adc/README.md) -* [凌智视觉模块 PWM 使用指南](./example/periphery/pwm/README.md) -* [凌智视觉模块 GPIO 使用指南](./example/periphery/gpio/README.md) -* [凌智视觉模块摄像头使用指南](./example/periphery/capture/README.md) +* [凌智视觉模块 ADC 使用指南](./example/periphery/adc) +* [凌智视觉模块 Capture(摄像头) 使用指南](./example/periphery/capture) +* [凌智视觉模块 GPIO 使用指南](./example/periphery/gpio) +* [凌智视觉模块 PWM 使用指南](./example/periphery/pwm) +* [凌智视觉模块 USART(串口) 使用指南](./example/periphery/usart) ## 🧠 深度学习视觉部署教程 这一部分教程将引导你从零开始训练并部署各种深度学习模型,包括分类模型、检测模型、分割模型和 OCR 模型。通过这些实战教程,你将学习到如何利用 Lockzhiner Vision Module 的高性能计算能力以及借助 Paddle 生态系统的丰富资源,轻松实现视觉任务的训练和部署。 -* [分类模型部署指南](./example/vision/classification/README.md) -* [检测模型部署指南(支持中)]() -* [分割模型部署指南(支持中)]() -* [OCR 模型部署指南(支持中)]() +* [凌智视觉模块分类模型部署指南](./example/vision/classification) +* [凌智视觉模块检测模型部署指南](./example/vision/detetcion) + + -## 👍 特色模型部署教程 +## 👍 特色部署教程 -* [手写数字检测部署指南(支持中)]() -* [人脸佩戴口罩检测部署指南(支持中)]() -* [二维码识别与检测部署指南(支持中)]() +* [凌智视觉模块手写数字识别部署指南](./example/special/digit_handwritten_recognition) +* [凌智视觉模块二维码识别与检测部署指南](。/example/special/qr_code_recognition) + ## 🐛 Bug反馈 @@ -79,6 +104,12 @@ Lockzhiner Vision Module 拥有丰富的 IO 接口,其接口图片如下图所 ## 😊 致谢 +凌智视觉模块(Lockzhiner Vision Module) 离不开社区的支持,特别感谢以下个人(或团体): + +* 感谢 Rockchip NPU 团队帮忙调试 Paddle 模型到 RKNN 模型的推理和优化 +* 感谢 PaddlePaddle 团队在适配 PaddleX 等套件上提供的帮助 +* 感谢 nihui 大佬帮忙审核并将 Lockzhiner Vision Module 的 ISP 代码合入到 opencv-mobile + ## 📜 开源协议 -Lockzhiner Vision Module 全系列仓库遵循 [Apache License Version 2.0](./LICENSE)。 \ No newline at end of file +Lockzhiner Vision Module 全系列仓库遵循 [Apache License Version 2.0](./LICENSE)。 diff --git a/configs/LZ-MobileNetV3.yaml b/configs/LZ-MobileNetV3.yaml index 12d2f243fc4a4df7b7a820beb85805c22be5ffc1..cf097aa5cd647f8c8712335d6360beb0214d6026 100644 --- a/configs/LZ-MobileNetV3.yaml +++ b/configs/LZ-MobileNetV3.yaml @@ -1,12 +1,12 @@ config: mean: - - 0.5 - - 0.5 - - 0.5 + - 0.406 + - 0.456 + - 0.485 std: - - 0.5 - - 0.5 - - 0.5 + - 0.225 + - 0.224 + - 0.229 load_onnx: inputs: diff --git a/configs/LZ-Picodet.yaml b/configs/LZ-Picodet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..af327bb2fe1fa9f801a43f4c06f585428e19dbfc --- /dev/null +++ b/configs/LZ-Picodet.yaml @@ -0,0 +1,32 @@ +config: + mean: + - 0.406 + - 0.456 + - 0.485 + std: + - 0.225 + - 0.224 + - 0.229 + +load_onnx: + inputs: + - image + input_size_list: + - + - 1 + - 3 + - 320 + - 320 + outputs: + - p2o.DequantizeLinear.1705 + - p2o.DequantizeLinear.1707 + - p2o.DequantizeLinear.1619 + - p2o.DequantizeLinear.1621 + - p2o.DequantizeLinear.1533 + - p2o.DequantizeLinear.1535 + - p2o.DequantizeLinear.1445 + - p2o.DequantizeLinear.1447 + +build: + do_quantization: false + dataset: \ No newline at end of file diff --git a/docs/device_parameters.md b/docs/device_parameters.md new file mode 100644 index 0000000000000000000000000000000000000000..9cfcd4279a198cb93ba75e5585cd47bc8bbc2c6b --- /dev/null +++ b/docs/device_parameters.md @@ -0,0 +1,115 @@ +

凌智视觉模块设备详细参数文档

+ +发布版本:V0.0.0 + +日期:2024-09-27 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司** +)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +|:-----------|--------|--------|----------| +| 2024/09/27 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +凌智视觉模块(Lockzhiner Vision Module) 是福州市凌睿智捷电子有限公司联合百度 PaddlePaddle +倾力打造的一款高集成度人工智能视觉模块,专为边缘端人工智能和机器视觉应用而设计,其特色包括: + +- 卓越的计算能力:Lockzhiner Vision Module 搭载单核 ARM Cortex-A7 处理器,并集成了 NEON 和 FPU,以更出色地处理 SIMD + 和浮点计算。同时,该模块支持 Int8 量化,内置 0.5 TOPs 的 NPU,足以应对绝大多数的视觉应用场景。 +- 广泛的开源适配:Lockzhiner Vision Module 与 PaddleClas、PaddleDetection、PaddleSeg、PaddleOCR 等基于 Paddle + 框架的视觉场景库完美适配。配合 AIStudio,用户可以实现一键训练、一键部署,从而极大地减轻了部署负担。 + +## 2 主控芯片参数 + +| 芯片参数 | 凌智视觉模块 | OpenMV4 H7 PLUS | +|:------:|:--------------------------:|:--------------------:| +| 主控芯片 | RV1106G3 | STM32H743II | +| 芯片架构 | ARM Cortex-A7 + NEON + FPU | ARM Cortex M7 | +| 主频 | 1.2GHz | 480 MHz | +| 内存 | 256MB DDR3L | 1MB RAM + 2 MB flash | +| NPU | 1 T int4 / 0.5 T int8 | 无 | +| ISP | 最大输入5M @30fps | 无 | +| 摄像头接口 | MIPI CSI 2-lane | 未知 | +| 默认存储介质 | SD 卡 | SD 卡 | + +## 3 外设参数 + +| 外设信息 | 参数介绍 | +|:-----:|---------------------------------------------------------------------------------------------------------------------| +| ADC | 1. 10 bit 分辨率
2. 1 MSPS 采样率
3. 单端输入,输入范围 0V - 1.8V | +| Capture | 1. 最大分辨率为(2304x1296)
2. 提供 opencv 库来调用摄像头
3. 可自由设置长宽为 8 的倍数 | +| GPIO | 1. 高电平 3.3V
2. 可产生中断
3. 支持电平触发和边沿触发
4. 可配置电平触发中断的极性
5. 配置上升沿,下降沿和双边沿触发中断
6. 可配置弱上拉或弱下拉
7. 可配置驱动能力 | +| PWM | 1. 可编程对总线时钟的预分频
2. 32 位定时器计数器
3. 支持捕获模式
4. 支持连续模式或单次模式;提供参考模式,并能输出多种占空比的波形
5. 兼容IR应用 | +| USART | 1. 嵌入 2 路 64 字节 FIFO,RX 和 TX 独立操作
2. 5-8位串行数据发送或接收
3. 标准异步通信位,如起始,停止,校验
4. 波特率高达 4 Mbps
5. 支持自动流控模式 | + +## 4 内置算法参数 + +| 算法名称 | 摄像头输入尺寸 | 模型输入尺寸 | 是否支持 | FPS | 是否实时 | +|:--------------------------:|:-------:|:---------:|:----:|:---:|:----:| +| 目标分类(PaddleClas 定制模型) | 任意 | (224x224) | 支持 | 40 | 是 | +| 目标检测(PaddleDetection 定制模型) | 任意 | (320x320) | 支持 | 25 | 是 | +| 手写数字识别(PaddleClas 定制模型) | 任意 | (224x224) | 支持 | 35 | 是 | +| 二维码识别(优化 zxing-cpp 算法) | 任意 | - | 支持 | 50 | 是 | + +> 注: +> +> - 以上算法在和摄像头搭配时,受限于摄像头帧率(25 FPS),实际帧率可能会有所下降,但均能保证实时! + +## 5 可拓展配件介绍 + +| 配件名称 | 详细介绍 | +|:-------:|:--------------------:| +| 电池 | 预留锂电池,3.7 V,XH2.0连接器 | +| WIFI 模组 | - | + +## 6 同类产品对比 + +### 6.1 外设参数对比 + +| 外设信息 | 凌智视觉模块 | OpenMV4 H7 PLUS | 编程方式 | +|:-----:|:-----------:|:---------------:|:------:| +| ADC | 支持 | 支持 | Python | +| I2C | 支持中 | 支持 | Python | +| GPIO | 最高支持 7 个 | 仅支持 2 个 | Python | +| PWM | 支持 | 支持 | Python | +| USART | 最高支持 2 个 | 支持 2 个 | Python | +| 摄像头 | (2304x1296) | (2592×1944) | Python | + +> 注: +> +> - OpenMV4 H7 PLUS 最高支持摄像头分辨率为 (2592×1944) ,但一般只能在 (320×240)及以下的分辨率时,实现简单算法 25 FPS(实时) + ;凌智视觉模块最高支持的摄像头分辨率为(2304x1296),但可以在 (960x540) 分辨率甚至更高的分辨率上的情况下,实现复杂算法 25 + FPS(实时) +> - 凌智视觉模块在不挂载 WIFI 模组的情况下最高支持 7 个 GPIO 同时使用,挂载 WIFI 模组的情况下,最高支持 2 个 GPIO 同时使用 +> - 凌智视觉模块的最高支持两个串口,但其中一个串口已经用于作为 Debug 口,暂不对外开放 + +### 6.2 算法参数对比 + +| 算法名称 | 凌智视觉模块 | OpenMV4 H7 PLUS | 编程方式 | +|:------:|------------------------------------------------------|----------------------------------------------------|:------:| +| 目标分类 | 1. 输入尺寸: (224x224)
2. 帧率: 最高 40 FPS | 1. 输入尺寸: (240x240)
2. 帧率: 15 FPS | Python | +| 目标检测 | 1. 输入尺寸: (320x320)
2. 帧率: 最高 25 FPS | 不支持 | Python | +| 手写数字识别 | 1. 输入尺寸: (224x224)
2. 帧率: 最高 35 FPS
3. 提供预训练模型 | 1. 输入尺寸: (240x240)
2. 帧率: 15 FPS
3. 不提供预训练模型 | Python | +| 二维码识别 | 1. 输入尺寸: 任意
2. 帧率: (640x480)下达到 50 FPS | 1. 输入尺寸: 任意
2. 帧率: 25-50 FPS | Python | +| 人脸检测 | 支持中 | 支持 | Python | +| 口罩佩戴检测 | 支持中 | 支持 | Python | +| 人脸识别 | 支持中 | 支持 | Python | diff --git a/docs/introductory_tutorial/burn_image.md b/docs/introductory_tutorial/burn_image.md index c2ae3c0619a19f1cbe5cc41c6ecd65d3120848af..5d732119b7240dc2778787dded8c5312217a545a 100644 --- a/docs/introductory_tutorial/burn_image.md +++ b/docs/introductory_tutorial/burn_image.md @@ -1,8 +1,8 @@

凌智视觉模块烧录镜像指南

-发布版本:V0.0.1 +发布版本:V0.0.0 -日期:2024-08-30 +日期:2024-09-26 文件密级:□绝密 □秘密 □内部资料 ■公开 @@ -25,8 +25,7 @@ | **日期** | **版本** | **作者** | **修改说明** | | :--------- | -------- | -------- | ------------ | -| 2024/08/30 | 0.0.0 | 黄展坤 | 初始版本 | -| 2024/08/30 | 0.0.1 | 郑必城 | 优化文档 | +| 2024/09/26 | 0.0.0 | 黄展坤 | 初始版本 | ## 1 简介 @@ -68,6 +67,12 @@ ![](images/burn_image/create_sd.png) -## 4 验证是否烧录成功 +## 4 插入 SD 卡 + +将 SD 卡插入 Lockzhiner Vision Module + +![](images/burn_image/insert_sd.png) + +## 5 验证是否烧录成功 烧录完成后,请将 SD 卡插入 Lockzhiner Vision Module,并参考 [连接设备指南](./connect_device_using_ssh.md) 来连接设备并输出 Hello World \ No newline at end of file diff --git a/docs/introductory_tutorial/connect_device_using_ssh.md b/docs/introductory_tutorial/connect_device_using_ssh.md index 1980d6d7fa3d3fc7a87574e566c686e57f087dc5..a07bdd1a0cea508a2402e350b0e6c90c203fe8ee 100644 --- a/docs/introductory_tutorial/connect_device_using_ssh.md +++ b/docs/introductory_tutorial/connect_device_using_ssh.md @@ -1,8 +1,8 @@

凌智视觉模块连接设备指南

-发布版本:V0.0.1 +发布版本:V0.0.0 -日期:2024-08-28 +日期:2024-09-26 文件密级:□绝密 □秘密 □内部资料 ■公开 @@ -25,8 +25,7 @@ | **日期** | **版本** | **作者** | **修改说明** | | :--------- | -------- | -------- | ------------ | -| 2024/08/01 | 0.0.0 | 杨宁 | 初始版本 | -| 2024/08/28 | 0.0.1 | 郑必城 | 修复文档错误 | +| 2024/09/26 | 0.0.0 | 黄展坤 | 初始版本 | ## 1 简介 diff --git a/docs/introductory_tutorial/cpp_development_environment.md b/docs/introductory_tutorial/cpp_development_environment.md index d17471b7c59ebf66820b1580573d1b923ae69709..feb1b97173366d909c9856e28c199f231551d198 100644 --- a/docs/introductory_tutorial/cpp_development_environment.md +++ b/docs/introductory_tutorial/cpp_development_environment.md @@ -1,8 +1,8 @@

凌智视觉模块 C++ 开发环境搭建指南

-发布版本:V0.0.2 +发布版本:V0.0.0 -日期:2024-09-11 +日期:2024-09-26 文件密级:□绝密 □秘密 □内部资料 ■公开 @@ -25,9 +25,7 @@ | **日期** | **版本** | **作者** | **修改说明** | | :--------- | -------- | -------- | ------------ | -| 2024/08/29 | 0.0.0 | 郑必城 | 初始版本 | -| 2024/09/07 | 0.0.1 | 郑必城 | 统一配置开发环境 | -| 2024/09/11 | 0.0.2 | 郑必城 | 优化文档 | +| 2024/09/26 | 0.0.0 | 黄展坤 | 初始版本 | ## 1 简介 @@ -59,8 +57,6 @@ Lockzhiner Vision Module 的 C++ 开发依赖 Ubuntu 系统,但是大多数用 ![](images/development_environment/Snipaste_2024-08-29_09-58-31.png) -![](images/development_environment/Snipaste_2024-08-29_09-59-40.png) - 安装完成后将会自动打开 Docker Destop,如下图 ![](images/development_environment/docker_destop.png) diff --git a/docs/introductory_tutorial/images/burn_image/insert_sd.png b/docs/introductory_tutorial/images/burn_image/insert_sd.png new file mode 100644 index 0000000000000000000000000000000000000000..e6900b57abe4fbeb3e068f2776221a6660e36f8b Binary files /dev/null and b/docs/introductory_tutorial/images/burn_image/insert_sd.png differ diff --git a/example/periphery/adc/README.md b/example/periphery/adc/README.md index 59a429183522fa8d251db2ebcfed42227966f887..42f97fab0121c4b7c3d75b2a3a5468da07b5f1da 100644 --- a/example/periphery/adc/README.md +++ b/example/periphery/adc/README.md @@ -51,7 +51,7 @@ ## 3 在凌智视觉模块上部署 ADC 例程 -请参考以下教程使用 C++ 或 Python 在凌智视觉模块上部署 ADC 例程: +请参考以下教程在凌智视觉模块上部署 ADC 例程: -* [凌智视觉模块 ADC C++ 部署指南](./cpp/README.md) + * [凌智视觉模块 ADC Python 部署指南](./python/README.md) \ No newline at end of file diff --git a/example/periphery/adc/python/README.md b/example/periphery/adc/python/README.md index 40a1f3d10cb9b6c6914c03b1fa352c8940e3c4a1..dd13a67582198c88ae5d25e528a4267b317bcb7f 100644 --- a/example/periphery/adc/python/README.md +++ b/example/periphery/adc/python/README.md @@ -63,7 +63,7 @@ class ADCBase: 该方法调用具体的 ADC 实例的 read 方法,返回读取到的 ADC 数据。 - @return 读取到的 ADC 数据 + @return 读取到的 ADC 数据,单位为 mV """ return self.adc.read() @@ -99,14 +99,13 @@ if __name__ == "__main__": 在 Lockzhiner Vision Module 上运行以下代码来执行 ADC 测试程序 ```bash -chmod +x ./Test-ADC -./Test-ADC +python test_adc.py ``` ![](images/result.png) 可以看到有一定的误差,误差一般在10mv以内 -## 5 其他 + -如果你需要使用 C++ 来部署 ADC 例程请参考[凌智视觉模块 ADC C++ 部署指南](../cpp/README.md)。 \ No newline at end of file + diff --git a/example/periphery/capture/README.md b/example/periphery/capture/README.md index a1be3798eb53fc0544eb744623dbd6ece4d2191c..88092ba3715f8445f6f3092b21945f4d144664bc 100644 --- a/example/periphery/capture/README.md +++ b/example/periphery/capture/README.md @@ -1,4 +1,4 @@ -

凌智视觉模块摄像头使用指南

+

凌智视觉模块摄像头部署指南

发布版本:V0.0.0 @@ -59,203 +59,11 @@ Lockzhiner Vision Module 上自带了一个摄像头,该摄像头可以支持 在开始这个章节前,请确保: -- 你已经按照 [开发环境搭建指南](../../../docs/introductory_tutorial/development_environment.md) 正确配置了开发环境。 -- 点击 [凌智视觉模块图片传输助手下载地址](https://gitee.com/LockzhinerAI/LockzhinerVisionModule/releases/download/v0.0.0/LockzhinerVisionModuleImageFetcher_v0.0.0.exe) 下载凌智视觉模块图片传输助手。 +- 点击 [凌智视觉模块图片传输助手下载地址](https://gitee.com/LockzhinerAI/LockzhinerVisionModule/releases/download/v0.0.0/LockzhinerVisionModuleImageFetcher.exe) 下载凌智视觉模块图片传输助手。 -## 4 API 文档 +## 4 在凌智视觉模块上部署摄像头例程 -### 4.1 读取摄像头文档 +请参考以下教程在凌智视觉模块上部署上部署摄像头例程: -凌智视觉模块使用 opencv-mobile 来读取摄像头数据。关于摄像头读取,请参考传统的 OpenCV 摄像头 API 来实现,需要注意的是: - -- 受限于运行内存,请使用我们编译的 [OpenCV Mobile](https://gitee.com/LockzhinerAI/opencv-mobile) 库来代替传统的 OpenCV 库 -- LockzhinerVisionModule 只有一个摄像头,因此在打开摄像头时,不管输入什么参数,都只会打开这个摄像头 -- 配置摄像头长宽时,请保证长和宽都是 8 的倍数 - -### 4.2 传输摄像头数据文档 - -为了让大家直观的看到摄像头获取的数据,我们编写了凌智视觉模块图片传输助手。关于 Lockzhiner Vision Module 中的图片发送 API,请参考以下文档: - -```cpp -/** - * @brief Edit 类提供了对摄像头数据的控制接口。 - * - * 需要注意的是, Edit 传输的数据必须使用 Lockzhiner Vision Module 图片获取助手来接收 - */ -class Edit { - public: - Edit() = default; - ~Edit() = default; - - /** - * @brief 接收客户端连接 - * - * 此函数尝试阻塞等待客户端连接。 - * 成功时返回 true,失败时返回 false。 - * - * @return bool 指示操作是否成功。 - */ - bool StartAndAcceptConnection(); - - /** - * @brief 输出图片 - * - * 此函数尝试向客户端传输图片数据 - * 成功时返回 true,失败时返回 false。 - * - * @return bool 指示操作是否成功。 - */ - bool Print(const cv::Mat &mat); - - private: - int server_fd_; - int port_ = 6868; - int new_socket_; - - void BuildPacket(const cv::Mat &mat, uint8_t *buffer, uint64_t size); - bool Write(const void *buf, size_t len); -}; -``` - -## 5 项目介绍 - -为了方便大家入手,我们做了一个简易的图片传输例程。该例程接收 Lockzhiner Vision Module 图片获取助手的连接并向其传输图片数据。 - -```cmake -# CMake最低版本要求 -cmake_minimum_required(VERSION 3.10) - -project(test_adc) - -# 定义项目根目录路径 -set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../..") -# 定义 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) - -# 配置摄像头数据 -add_executable(Test-Capture test_capture.cc) -target_include_directories(Test-Capture PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS}) -target_link_libraries(Test-Capture PRIVATE ${OPENCV_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES}) -``` - -读取并传输摄像头数据的核心代码如下: - -```cpp -#include - -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - int width = 640; - int height = 480; - if (argc == 3) { - width = atoi(argv[1]); - height = atoi(argv[2]); - } - - lockzhiner_vision_module::edit::Edit edit; - // 打开服务器并阻塞接收客户端连接 - if (!edit.StartAndAcceptConnection()) { - std::cout << "Failed to start and accept connection" << std::endl; - return 1; - } - std::cout << "Succeed to connect device" << std::endl; - - cv::VideoCapture cap; - // 设置摄像头长宽 - cap.set(cv::CAP_PROP_FRAME_WIDTH, width); - cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); - // 打开摄像头 - cap.open(0); - - const int w = cap.get(cv::CAP_PROP_FRAME_WIDTH); - const int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT); - cv::Mat temp_mat; - while (true) { - cap >> temp_mat; - // 判断获取的图片是否为空 - if (temp_mat.empty()) { - continue; - } - // 向客户端输出图片 - if (!edit.Print(temp_mat)) { - std::cout << "Failed to print to edit" << std::endl; - break; - } - } - return 0; -} -``` - -## 6 编译项目 - -使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 - -```bash -# 进入 Demo 目录 -cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/example/periphery/capture - -# 创建编译目录 -rm -rf build && mkdir build && cd build - -# 配置交叉编译工具链 -export TOOLCHAIN_ROOT_PATH=${PWD}/../../../../../arm-rockchip830-linux-uclibcgnueabihf - -# 使用 cmake 配置项目 -cmake -DCMAKE_TOOLCHAIN_FILE=../../../../toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - .. - -# 执行编译 -make -j8 -``` - -![](images/build_example.png) - -## 7 执行摄像头测试程序 - -参考 [连接设备指南](../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 - -![](../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) - -参考之前的例程,将 **Test-Capture** 传输到 Lockzhiner Vision Module 上 - -![](images/sftp.png) - -传输完成后执行以下代码 - -```bash -chmod +x ./Test-Capture -./Test-Capture -``` - -代码开启后程序将阻塞并等待摄像头连接 - -![](images/result_0.png) - -打开下载的 Lockzhiner Vision Module 图片获取助手,点击连接设备 - -![](images/result_1.png) - -成功连接设备后,将出现摄像头的画面 - -> 提示: -> 如果摄像头的画面不够清晰,请尝试轻轻转动摄像头来调整合适的焦距 - -![](images/result_2.png) - -点击拍照保存可以将图片保存到程序保存路径下的 **LockzhinerVisionModuleImages** 文件夹中 - -![](images/result_3.png) - -你可以点击**打开保存文件夹**按钮来快速打开这个文件夹 + +* [凌智视觉模块摄像头 Python 部署指南](./python/README.md) \ No newline at end of file diff --git a/example/periphery/capture/CMakeLists.txt b/example/periphery/capture/cpp/CMakeLists.txt similarity index 100% rename from example/periphery/capture/CMakeLists.txt rename to example/periphery/capture/cpp/CMakeLists.txt diff --git a/example/periphery/capture/cpp/README.md b/example/periphery/capture/cpp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a1be3798eb53fc0544eb744623dbd6ece4d2191c --- /dev/null +++ b/example/periphery/capture/cpp/README.md @@ -0,0 +1,261 @@ +

凌智视觉模块摄像头使用指南

+ +发布版本:V0.0.0 + +日期:2024-09-04 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/04 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +Lockzhiner Vision Module 上自带了一个摄像头,该摄像头可以支持最大 **2304x1296(16:9)** 的分辨率。本章节中,我们将教会你如何使用 Lockzhiner Vision Module 读取 摄像头数据,并使用 Lockzhiner Vision Module 传输图片到本地,方便保存数据。 + +## 2 数据表 + +受限于解码能力,Lockzhiner Vision Module 在不同的分辨率下,摄像头的帧率是不一样的,具体可以参考如下表格: + +### 2.1 长宽比为 4:3 + +| 摄像头分辨率| FPS | +| :----: | :----: | +| 480x360(4:3) | 25 | +| 640x480(4:3) | 25 | +| 960x720(4:3) | 14 | +| 1280x960(4:3) | 13 | +| 1920x1440(4:3) | 13 | + +### 2.2 长宽比为 16:9 + +| 摄像头分辨率| FPS | +| :----: | :----: | +| 480x270(16:9) | 25 | +| 640x360(16:9) | 25 | +| 960x540(16:9) | 25 | +| 1280x720(16:9) | 15 | +| 1920x1080(16:9) | 12 | + +## 3 前期准备 + +在开始这个章节前,请确保: + +- 你已经按照 [开发环境搭建指南](../../../docs/introductory_tutorial/development_environment.md) 正确配置了开发环境。 +- 点击 [凌智视觉模块图片传输助手下载地址](https://gitee.com/LockzhinerAI/LockzhinerVisionModule/releases/download/v0.0.0/LockzhinerVisionModuleImageFetcher_v0.0.0.exe) 下载凌智视觉模块图片传输助手。 + +## 4 API 文档 + +### 4.1 读取摄像头文档 + +凌智视觉模块使用 opencv-mobile 来读取摄像头数据。关于摄像头读取,请参考传统的 OpenCV 摄像头 API 来实现,需要注意的是: + +- 受限于运行内存,请使用我们编译的 [OpenCV Mobile](https://gitee.com/LockzhinerAI/opencv-mobile) 库来代替传统的 OpenCV 库 +- LockzhinerVisionModule 只有一个摄像头,因此在打开摄像头时,不管输入什么参数,都只会打开这个摄像头 +- 配置摄像头长宽时,请保证长和宽都是 8 的倍数 + +### 4.2 传输摄像头数据文档 + +为了让大家直观的看到摄像头获取的数据,我们编写了凌智视觉模块图片传输助手。关于 Lockzhiner Vision Module 中的图片发送 API,请参考以下文档: + +```cpp +/** + * @brief Edit 类提供了对摄像头数据的控制接口。 + * + * 需要注意的是, Edit 传输的数据必须使用 Lockzhiner Vision Module 图片获取助手来接收 + */ +class Edit { + public: + Edit() = default; + ~Edit() = default; + + /** + * @brief 接收客户端连接 + * + * 此函数尝试阻塞等待客户端连接。 + * 成功时返回 true,失败时返回 false。 + * + * @return bool 指示操作是否成功。 + */ + bool StartAndAcceptConnection(); + + /** + * @brief 输出图片 + * + * 此函数尝试向客户端传输图片数据 + * 成功时返回 true,失败时返回 false。 + * + * @return bool 指示操作是否成功。 + */ + bool Print(const cv::Mat &mat); + + private: + int server_fd_; + int port_ = 6868; + int new_socket_; + + void BuildPacket(const cv::Mat &mat, uint8_t *buffer, uint64_t size); + bool Write(const void *buf, size_t len); +}; +``` + +## 5 项目介绍 + +为了方便大家入手,我们做了一个简易的图片传输例程。该例程接收 Lockzhiner Vision Module 图片获取助手的连接并向其传输图片数据。 + +```cmake +# CMake最低版本要求 +cmake_minimum_required(VERSION 3.10) + +project(test_adc) + +# 定义项目根目录路径 +set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../..") +# 定义 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) + +# 配置摄像头数据 +add_executable(Test-Capture test_capture.cc) +target_include_directories(Test-Capture PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS}) +target_link_libraries(Test-Capture PRIVATE ${OPENCV_LIBRARIES} ${LOCKZHINER_VISION_MODULE_LIBRARIES}) +``` + +读取并传输摄像头数据的核心代码如下: + +```cpp +#include + +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + int width = 640; + int height = 480; + if (argc == 3) { + width = atoi(argv[1]); + height = atoi(argv[2]); + } + + lockzhiner_vision_module::edit::Edit edit; + // 打开服务器并阻塞接收客户端连接 + if (!edit.StartAndAcceptConnection()) { + std::cout << "Failed to start and accept connection" << std::endl; + return 1; + } + std::cout << "Succeed to connect device" << std::endl; + + cv::VideoCapture cap; + // 设置摄像头长宽 + cap.set(cv::CAP_PROP_FRAME_WIDTH, width); + cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); + // 打开摄像头 + cap.open(0); + + const int w = cap.get(cv::CAP_PROP_FRAME_WIDTH); + const int h = cap.get(cv::CAP_PROP_FRAME_HEIGHT); + cv::Mat temp_mat; + while (true) { + cap >> temp_mat; + // 判断获取的图片是否为空 + if (temp_mat.empty()) { + continue; + } + // 向客户端输出图片 + if (!edit.Print(temp_mat)) { + std::cout << "Failed to print to edit" << std::endl; + break; + } + } + return 0; +} +``` + +## 6 编译项目 + +使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 + +```bash +# 进入 Demo 目录 +cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/example/periphery/capture + +# 创建编译目录 +rm -rf build && mkdir build && cd build + +# 配置交叉编译工具链 +export TOOLCHAIN_ROOT_PATH=${PWD}/../../../../../arm-rockchip830-linux-uclibcgnueabihf + +# 使用 cmake 配置项目 +cmake -DCMAKE_TOOLCHAIN_FILE=../../../../toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + .. + +# 执行编译 +make -j8 +``` + +![](images/build_example.png) + +## 7 执行摄像头测试程序 + +参考 [连接设备指南](../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +参考之前的例程,将 **Test-Capture** 传输到 Lockzhiner Vision Module 上 + +![](images/sftp.png) + +传输完成后执行以下代码 + +```bash +chmod +x ./Test-Capture +./Test-Capture +``` + +代码开启后程序将阻塞并等待摄像头连接 + +![](images/result_0.png) + +打开下载的 Lockzhiner Vision Module 图片获取助手,点击连接设备 + +![](images/result_1.png) + +成功连接设备后,将出现摄像头的画面 + +> 提示: +> 如果摄像头的画面不够清晰,请尝试轻轻转动摄像头来调整合适的焦距 + +![](images/result_2.png) + +点击拍照保存可以将图片保存到程序保存路径下的 **LockzhinerVisionModuleImages** 文件夹中 + +![](images/result_3.png) + +你可以点击**打开保存文件夹**按钮来快速打开这个文件夹 diff --git a/example/periphery/capture/images/build_example.png b/example/periphery/capture/cpp/images/build_example.png similarity index 100% rename from example/periphery/capture/images/build_example.png rename to example/periphery/capture/cpp/images/build_example.png diff --git a/example/periphery/capture/images/result_0.png b/example/periphery/capture/cpp/images/result_0.png similarity index 100% rename from example/periphery/capture/images/result_0.png rename to example/periphery/capture/cpp/images/result_0.png diff --git a/example/periphery/capture/images/sftp.png b/example/periphery/capture/cpp/images/sftp.png similarity index 100% rename from example/periphery/capture/images/sftp.png rename to example/periphery/capture/cpp/images/sftp.png diff --git a/example/periphery/capture/test_capture.cc b/example/periphery/capture/cpp/test_capture.cc similarity index 100% rename from example/periphery/capture/test_capture.cc rename to example/periphery/capture/cpp/test_capture.cc diff --git a/example/periphery/capture/python/README.md b/example/periphery/capture/python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7f5c554218a25ab870df50e2acda26d0f9fcd391 --- /dev/null +++ b/example/periphery/capture/python/README.md @@ -0,0 +1,199 @@ +

凌智视觉模块摄像头 Python 部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-25 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/25 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +Lockzhiner Vision Module 上自带了一个摄像头,该摄像头可以支持最大 **2304x1296(16:9)** 的分辨率。本章节中,我们将教会你如何使用 Lockzhiner Vision Module 读取 摄像头数据,并使用 Lockzhiner Vision Module 传输图片到本地,方便保存数据。 + +## 2 前期准备 + +在开始这个章节前,请确保: + +- 你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 +- 参考 [凌智视觉模块摄像头部署指南](../README.md) 下载凌智视觉模块图片传输助手。 + +## 3 API 文档 + +### 3.1 读取摄像头文档 + +读取摄像头的 API 对齐了 OpenCV,具体 API 文档如下: + +```python +class VideoCapture: + """ + OpenCV 摄像头类 + """ + def __init__(self): + self.video_capture = cv2.VideoCapture() + + def open(self, index=0): + """ + 打开摄像头 + + Returns: + bool: 摄像头打开过程过是否出现逻辑错误 + """ + return self.video_capture.open(index) + + def isOpened(self): + """ + 判断摄像头是否打开成功 + + Returns: + bool: 摄像头是否打开成功 + """ + return self.video_capture.isOpened() + + def read(self): + """ + 读取摄像头数据 + + Returns: + bool: 摄像头是否成功读取到数据 + cv::Mat: 摄像头读取的图像数据 + """ + mat = self.video_capture.read() + return not mat.empty(), mat + + def release(self): + """ + 关闭摄像头 + + Returns: + bool: 是否释放成功 + """ + return self.video_capture.release() +``` + +### 3.2 传输摄像头数据文档 + +为了让大家直观的看到摄像头获取的数据,我们编写了凌智视觉模块图片传输助手。关于 Lockzhiner Vision Module 中的图片发送 API,请参考以下文档: + +```python +class Edit: + """ + 图片数据传输类,用于传输 CV::Mat 到凌智图片传输助手 + """ + def __init__(self): + self.edit = edit.Edit() + + def start_and_accept_connection(self): + """ + 阻塞等待凌智图片传输助手的连接请求 + """ + return self.edit.start_and_accept_connection() + + def print(self, mat): + """ + 传输图片到凌智图片传输助手 + + Args: + mat (cv::Mat): OpenCV 图片 Array + + Returns: + bool: 传输是否成功 + """ + return self.edit.print(mat) +``` + +## 4 项目介绍 + +为了方便大家入手,我们做了一个简易的图片传输例程。该例程接收 Lockzhiner Vision Module 图片获取助手的连接并向其传输图片数据。 + +```cpp +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.edit import Edit +import time +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 1: + print("Need model path. Example: python test_capture.py") + exit(1) + + edit = Edit() + edit.start_and_accept_connection() + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + read_index = 0 + total_time_ms = 0 + for i in range(30): + start_time = time.time() + ret, mat = video_capture.read() + if ret is False: + continue + end_time = time.time() + edit.print(mat) + total_time_ms += end_time - start_time + read_index += 1 + print(f"FPS is {1.0 / (total_time_ms/read_index)}") +``` + +## 5 执行摄像头测试程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +参考之前的例程,将 **test_capture.py** 传输到 Lockzhiner Vision Module 上 + +![](images/sftp.png) + +传输完成后,返回代码执行界面,执行以下代码 + +```bash +python ./test_capture.py +``` + +代码开启后程序将阻塞并等待摄像头连接 + +![](images/result_0.png) + +打开下载的 Lockzhiner Vision Module 图片获取助手,点击连接设备 + +![](../images/result_1.png) + +成功连接设备后,将出现摄像头的画面 + +> 提示: +> 如果摄像头的画面不够清晰,请尝试轻轻转动摄像头来调整合适的焦距 + +![](../images/result_2.png) + +点击拍照保存可以将图片保存到程序保存路径下的 **LockzhinerVisionModuleImages** 文件夹中 + +![](../images/result_3.png) + +你可以点击**打开保存文件夹**按钮来快速打开这个文件夹 diff --git a/example/periphery/capture/python/images/result_0.png b/example/periphery/capture/python/images/result_0.png new file mode 100644 index 0000000000000000000000000000000000000000..8d869d51490773cfb91d0a09d4b2fca4e609852c Binary files /dev/null and b/example/periphery/capture/python/images/result_0.png differ diff --git a/example/periphery/capture/python/images/sftp.png b/example/periphery/capture/python/images/sftp.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7c203519091749a44dd45bcdcc9f57ee696f49 Binary files /dev/null and b/example/periphery/capture/python/images/sftp.png differ diff --git a/example/periphery/capture/python/test_capture.py b/example/periphery/capture/python/test_capture.py new file mode 100644 index 0000000000000000000000000000000000000000..c14b8a35e8d7a682823ad3cdcea22eaf9d456707 --- /dev/null +++ b/example/periphery/capture/python/test_capture.py @@ -0,0 +1,32 @@ +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.edit import Edit +import time +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 1: + print("Need model path. Example: python test_capture.py") + exit(1) + + edit = Edit() + edit.start_and_accept_connection() + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + read_index = 0 + total_time_ms = 0 + for i in range(30): + start_time = time.time() + ret, mat = video_capture.read() + if ret is False: + continue + end_time = time.time() + edit.print(mat) + total_time_ms += end_time - start_time + read_index += 1 + print(f"FPS is {1.0 / (total_time_ms/read_index)}") diff --git a/example/periphery/gpio/README.md b/example/periphery/gpio/README.md index c0d31b1c92b57343b6000a5d0f387b69c24275ad..cbd4e5be4e564599a95b0586fe8ad083805cbd3b 100644 --- a/example/periphery/gpio/README.md +++ b/example/periphery/gpio/README.md @@ -58,9 +58,9 @@ GPIO(General Purpose Input/Output,通用输入/输出)是一种在嵌入 在 Lockzhiner Vision Module 上运行以下代码来执行 GPIO 接收程序 -## 3 在凌智视觉模块上部署 ADC 例程 +## 3 在凌智视觉模块上部署 GPIO 例程 -请参考以下教程使用 C++ 或 Python 在凌智视觉模块上部署 GPIO 例程: +请参考以下教程在凌智视觉模块上部署 GPIO 例程: -- [凌智视觉模块 GPIO C++ 部署指南](./cpp/README.md) + - [凌智视觉模块 GPIO Python 部署指南](./python/README.md) diff --git a/example/periphery/gpio/cpp/README.md b/example/periphery/gpio/cpp/README.md index 3c544e36a8f0cd242f3795b153e9dec5f8aaa816..11a283d752110cdababbfc9df4eb17b4e4cf6c95 100644 --- a/example/periphery/gpio/cpp/README.md +++ b/example/periphery/gpio/cpp/README.md @@ -260,11 +260,11 @@ chmod +x ./Test-GPIO-Write 查看示波器可以看到,GPIO_0A0 输出了 3.4V 左右的电压 -![](images/show_0.png) +![](../images/show_0.png) 电压持续 10S 后恢复了正常 -![](images/show_1.png) +![](../images/show_1.png) ### 6.2 测试 GPIO 输入模式(输入高电平) @@ -277,7 +277,7 @@ chmod +x ./Test-GPIO-Read 可以看到,在接高电平引脚的情况下,引脚的状态信息为 1 -![](images/show_2.png) +![](../images/show_2.png) ### 6.3 测试 GPIO 输入模式(输入低电平) @@ -291,7 +291,7 @@ chmod +x ./Test-GPIO-Read 可以看到,在低电平引脚的情况下,引脚的状态信息为 0 -![](images/show_3.png) +![](../images/show_3.png) ## 7 其他 diff --git a/example/periphery/gpio/cpp/images/show_0.png b/example/periphery/gpio/images/show_0.png similarity index 100% rename from example/periphery/gpio/cpp/images/show_0.png rename to example/periphery/gpio/images/show_0.png diff --git a/example/periphery/gpio/cpp/images/show_1.png b/example/periphery/gpio/images/show_1.png similarity index 100% rename from example/periphery/gpio/cpp/images/show_1.png rename to example/periphery/gpio/images/show_1.png diff --git a/example/periphery/gpio/python/README.md b/example/periphery/gpio/python/README.md index ec03d92476687c02eb23c248ed49f3cb4e5d1b4f..c7fe4071a6d03bb8fa65bd55150b11905302c68f 100644 --- a/example/periphery/gpio/python/README.md +++ b/example/periphery/gpio/python/README.md @@ -37,11 +37,6 @@ ## 2 API 文档 ```python -from ..lockzhiner_vision_module_wapper import periphery - -from enum import Enum - - class GPIOMode(Enum): """ @class GPIOMode @@ -163,9 +158,91 @@ class GPIO2A5(GPIOBase): 测试 GPIO 输入模式的核心代码如下: ```python +from lockzhiner_vision_module.periphery import GPIO0A0, GPIOMode, GPIOState + + +if __name__ == "__main__": + gpio = GPIO0A0() + + if gpio.config(GPIOMode.IN) is False: + print("Failed to config gpio mode") + exit(1) + + state = gpio.read() + if state == GPIOState.ERROR: + print("Failed to read gpio mode") + exit(1) + + print(f"state is {state}") ``` 测试 GPIO 输出模式的核心代码如下: ```python -``` \ No newline at end of file +from lockzhiner_vision_module.periphery import GPIO0A0, GPIOMode, GPIOState +import time + +if __name__ == "__main__": + gpio = GPIO0A0() + + if gpio.config(GPIOMode.OUT) is False: + print("Failed to config gpio mode") + exit(1) + + if gpio.write(GPIOState.HIGH) is False: + print("Failed to write gpio state") + exit(1) + + time_index = 0 + total_time = 10 + while time_index < total_time: + print(f"Wait: {time_index}/{total_time}") + time_index += 1 + time.sleep(1) + + if gpio.write(GPIOState.LOW) is False: + print("Failed to write gpio state") + exit(1) +``` + +## 4 执行 GPIO 测试程序 + +### 4.1 测试 GPIO 输出模式 + +在 Lockzhiner Vision Module 上运行以下代码来执行 GPIO 输出电平程序 + +```bash +python test_gpio_read.py +``` + +查看示波器可以看到,GPIO_0A0 输出了 3.4V 左右的电压 + +![](../images/show_0.png) + +电压持续 10S 后恢复了正常 + +![](../images/show_1.png) + +### 4.2 测试 GPIO 输入模式(输入高电平) + +在 Lockzhiner Vision Module 上运行以下代码来执行 GPIO 接收程序 + +```bash +python test_gpio_write.py +``` + +可以看到,在接高电平引脚的情况下,引脚的状态信息为 GPIOState.LOW + +![](images/show_2.png) + +### 4.3 测试 GPIO 输入模式(输入低电平) + +在 Lockzhiner Vision Module 上运行以下代码来执行 GPIO 接收程序 + +```bash +python test_gpio_write.py +``` + +可以看到,在低电平引脚的情况下,引脚的状态信息为 GPIOState.HIGH + +![](images/show_3.png) diff --git a/example/periphery/gpio/python/images/show_2.png b/example/periphery/gpio/python/images/show_2.png new file mode 100644 index 0000000000000000000000000000000000000000..81839e85b134e5c64b0b2ab97f81ff14c1073a0e Binary files /dev/null and b/example/periphery/gpio/python/images/show_2.png differ diff --git a/example/periphery/gpio/python/images/show_3.png b/example/periphery/gpio/python/images/show_3.png new file mode 100644 index 0000000000000000000000000000000000000000..293d2049cea5bfa876c1ae0d448af8e15140d017 Binary files /dev/null and b/example/periphery/gpio/python/images/show_3.png differ diff --git a/example/periphery/gpio/python/test_gpio_read.py b/example/periphery/gpio/python/test_gpio_read.py index ca6812d2ecaba1a92967981e6aa66680cf7b3ddf..d7c84b4b8a8938112abad6da680b727ab626d20f 100644 --- a/example/periphery/gpio/python/test_gpio_read.py +++ b/example/periphery/gpio/python/test_gpio_read.py @@ -1,6 +1,4 @@ -from lockzhiner_vision_module.periphery import GPIO0A0 -from lockzhiner_vision_module.periphery import GPIOMode -from lockzhiner_vision_module.periphery import GPIOState +from lockzhiner_vision_module.periphery import GPIO0A0, GPIOMode, GPIOState if __name__ == "__main__": diff --git a/example/periphery/gpio/python/test_gpio_write.py b/example/periphery/gpio/python/test_gpio_write.py index 1bfcc8d8c60a7dfda1d459fb64280b60e43d7336..06b69ff92d84cf6b3d3d35ae771e8764d4ce3f72 100644 --- a/example/periphery/gpio/python/test_gpio_write.py +++ b/example/periphery/gpio/python/test_gpio_write.py @@ -1,6 +1,4 @@ -from lockzhiner_vision_module.periphery import GPIO0A0 -from lockzhiner_vision_module.periphery import GPIOMode -from lockzhiner_vision_module.periphery import GPIOState +from lockzhiner_vision_module.periphery import GPIO0A0, GPIOMode, GPIOState import time if __name__ == "__main__": diff --git a/example/periphery/pwm/README.md b/example/periphery/pwm/README.md index 1fad535db88074ff050a4bba25ed9b4e9312e28c..6f0521379dd4c926ddca2187a945982213718fb0 100644 --- a/example/periphery/pwm/README.md +++ b/example/periphery/pwm/README.md @@ -1,8 +1,8 @@ -

PWM 使用指南

+

凌智视觉模块 PWM 使用指南

发布版本:V0.0.0 -日期:2024-08-30 +日期:2024-09-26 文件密级:□绝密 □秘密 □内部资料 ■公开 @@ -25,180 +25,13 @@ | **日期** | **版本** | **作者** | **修改说明** | | :--------- | -------- | -------- | ------------ | -| 2024/08/30 | 0.0.0 | 郑必城 | 初始版本 | - +| 2024/09/26 | 0.0.0 | 郑必城 | 初始版本 | ## 1 简介 在电子工程和嵌入式系统开发中,脉冲宽度调制(PWM, Pulse Width Modulation)是一项关键技术,它允许我们通过调整脉冲信号的占空比来控制模拟信号的平均电平。 -## 2 前期准备 - -在开始这个章节前,请确保你已经按照 [开发环境搭建指南](../../../docs/introductory_tutorial/development_environment.md) 正确配置了开发环境。本章节中,我们将教会你如何控制 Lockzhiner Vision Module 上的 PWM 接口。 - -## 3 API 文档 - -```c++ -/** - * @brief PWM 类提供了对脉冲宽度调制(PWM)信号的控制接口。 - * - * 这个类允许用户打开、关闭 PWM 通道,并配置 PWM 信号的频率和占空比。 - * 需要注意的是, PWM 输出的电压在低电平时为 0V,高电平时为 3.3V。 - */ -class PWM { - public: - /** - * @brief PWM 类的构造函数。 - * - * 构造函数初始化 PWM 类的实例,但不自动打开 PWM 通道。 - */ - PWM(); - - /** - * @brief PWM 类的析构函数。 - * - * 析构函数负责清理 PWM 类实例使用的资源,但不会自动关闭 PWM 通道。 - * 建议在不需要 PWM 时显式调用 Close() 函数。 - */ - ~PWM(); - - /** - * @brief 打开 PWM 通道。 - * - * 此函数尝试打开 PWM 通道,但不配置任何参数(如频率和占空比)。 - * 成功时返回 true,失败时返回 false。 - * - * @return bool 指示操作是否成功。 - */ - bool Open(); - - /** - * @brief 关闭 PWM 通道。 - * - * 此函数关闭 PWM 通道,停止 PWM 信号的输出。 - * 成功时返回 true,失败时返回 false。 - * - * @return bool 指示操作是否成功。 - */ - bool Close(); - - /** - * @brief 配置 PWM 信号的频率和占空比。 - * - * 配置 PWM 信号的频率(以Hz为单位)和占空比(以 0.0 到 1.0 的浮点数表示)。 - * 成功时返回 true,失败时返回 false。 - * - * @param frequency PWM 信号的频率(Hz)。 - * @param duty_cycle PWM 信号的占空比(0.0 到 1.0 之间)。 - * @return bool 指示操作是否成功。 - */ - bool ConfigPWM(uint32_t frequency, float duty_cycle); - - /** - * @brief 打开 PWM 通道并配置频率与占空比。 - * - * 这是一个便捷的函数,它首先尝试打开 PWM 通道,然后配置 PWM - * 信号的频率和占空比。 如果任何一步失败,函数将返回 false。 - * - * @param frequency PWM 信号的频率(Hz)。 - * @param duty_cycle PWM 信号的占空比(0.0 到 1.0 之间)。 - * @return bool 指示操作是否成功。 - */ - bool Open(uint32_t frequency, float duty_cycle); -}; -``` - -## 4 项目介绍 - -为了方便大家入手,我们做了一个简易的 PWM 例程。该例程可以输出持续 10s 的 PWM 信号。 - -```cmake -# CMake最低版本要求 -cmake_minimum_required(VERSION 3.10) - -project(test_pwm) - -# 定义项目根目录路径 -set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../..") -# 定义 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) - -# 配置 PWM 读取例程 -add_executable(Test-PWM test_pwm.cc) -target_include_directories(Test-PWM PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS}) -target_link_libraries(Test-PWM PRIVATE ${LOCKZHINER_VISION_MODULE_LIBRARIES}) -``` - -例程的核心代码如下: - -```cpp -#include - -#include // 为了使用atoi() -#include // 为了使用strtof() -#include -#include - -int main(int argc, char* argv[]) { - uint32_t frequency = 1000000; - float duty_cycle = 0.5; - if (argc == 3) { - frequency = std::atoi(argv[1]); - duty_cycle = std::strtof(argv[2], nullptr); - } - std::cout << "frequency is " << frequency << std::endl; - std::cout << "duty_cycle is " << duty_cycle << std::endl; - - lockzhiner_vision_module::periphery::PWM pwm; - - // 打开 PWM - if (!pwm.Open(frequency, duty_cycle)) { - std::cout << "Failed to open adc." << std::endl; - return 1; - } - - for (int i = 0; i < 10; i++) { - std::cout << "Wait: " << i << "/" << 10 << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - // 关闭 PWM - if (!pwm.Close()) { - std::cout << "Failed to open adc." << std::endl; - return 1; - } - return 0; -} -``` - -## 5 编译项目 - -使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 - -```bash -# 进入 Demo 目录 -cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/example/periphery/pwm - -# 创建编译目录 -rm -rf build && mkdir build && cd build - -# 配置交叉编译工具链 -export TOOLCHAIN_ROOT_PATH=${PWD}/../../../../../arm-rockchip830-linux-uclibcgnueabihf - -# 使用 cmake 配置项目 -cmake -DCMAKE_TOOLCHAIN_FILE=../../../../toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - .. - -# 执行编译 -make -j8 -``` - -![](images/build_example.png) - -## 6 正确连接设备 +## 2 正确连接设备 > 注意: Lockzhiner Vision Module PWM 引脚输出的理论高电平为 3.3V,理论低电平为 0V @@ -211,30 +44,9 @@ make -j8 ![](../../../images/periphery.png) -## 7 执行 ADC 测试程序 - -参考 [连接设备指南](../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 - -![](../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) - -使用 SFTP 功能将软件上传到 Lockzhiner Vision Module - -![](images/sftp.png) - -在 Lockzhiner Vision Module 上运行以下代码来执行 ADC 测试程序 - -```bash -chmod +x ./Test-PWM -# ./Test-PWM 频率(默认为1MHZ) 占空比(默认为0.5) -./Test-PWM 100000 0.5 -``` - -程序运行开始后,屏幕上打印配置的频率和占空比并开始每隔一秒显示当前进度 - -![](images/pwm_start.png) -![](images/show_start.png) +## 3 在凌智视觉模块上部署 ADC 例程 -程序运行 10s 后,程序退出 PWM 停止 +请参考以下教程在凌智视觉模块上部署 PWM 例程: -![](images/pwm_end.png) -![](images/show_end.png) \ No newline at end of file + +- [凌智视觉模块 PWM Python 部署指南](./python/README.md) diff --git a/example/periphery/pwm/CMakeLists.txt b/example/periphery/pwm/cpp/CMakeLists.txt similarity index 100% rename from example/periphery/pwm/CMakeLists.txt rename to example/periphery/pwm/cpp/CMakeLists.txt diff --git a/example/periphery/pwm/cpp/README.md b/example/periphery/pwm/cpp/README.md new file mode 100644 index 0000000000000000000000000000000000000000..20bac8bd29db9c86b44c1a2655fa1e64d30ffd17 --- /dev/null +++ b/example/periphery/pwm/cpp/README.md @@ -0,0 +1,240 @@ +

PWM 使用指南

+ +发布版本:V0.0.0 + +日期:2024-08-30 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/08/30 | 0.0.0 | 郑必城 | 初始版本 | + + +## 1 简介 + +在电子工程和嵌入式系统开发中,脉冲宽度调制(PWM, Pulse Width Modulation)是一项关键技术,它允许我们通过调整脉冲信号的占空比来控制模拟信号的平均电平。 + +## 2 前期准备 + +在开始这个章节前,请确保你已经按照 [开发环境搭建指南](../../../docs/introductory_tutorial/development_environment.md) 正确配置了开发环境。本章节中,我们将教会你如何控制 Lockzhiner Vision Module 上的 PWM 接口。 + +## 3 API 文档 + +```c++ +/** + * @brief PWM 类提供了对脉冲宽度调制(PWM)信号的控制接口。 + * + * 这个类允许用户打开、关闭 PWM 通道,并配置 PWM 信号的频率和占空比。 + * 需要注意的是, PWM 输出的电压在低电平时为 0V,高电平时为 3.3V。 + */ +class PWM { + public: + /** + * @brief PWM 类的构造函数。 + * + * 构造函数初始化 PWM 类的实例,但不自动打开 PWM 通道。 + */ + PWM(); + + /** + * @brief PWM 类的析构函数。 + * + * 析构函数负责清理 PWM 类实例使用的资源,但不会自动关闭 PWM 通道。 + * 建议在不需要 PWM 时显式调用 Close() 函数。 + */ + ~PWM(); + + /** + * @brief 打开 PWM 通道。 + * + * 此函数尝试打开 PWM 通道,但不配置任何参数(如频率和占空比)。 + * 成功时返回 true,失败时返回 false。 + * + * @return bool 指示操作是否成功。 + */ + bool Open(); + + /** + * @brief 关闭 PWM 通道。 + * + * 此函数关闭 PWM 通道,停止 PWM 信号的输出。 + * 成功时返回 true,失败时返回 false。 + * + * @return bool 指示操作是否成功。 + */ + bool Close(); + + /** + * @brief 配置 PWM 信号的频率和占空比。 + * + * 配置 PWM 信号的频率(以Hz为单位)和占空比(以 0.0 到 1.0 的浮点数表示)。 + * 成功时返回 true,失败时返回 false。 + * + * @param frequency PWM 信号的频率(Hz)。 + * @param duty_cycle PWM 信号的占空比(0.0 到 1.0 之间)。 + * @return bool 指示操作是否成功。 + */ + bool ConfigPWM(uint32_t frequency, float duty_cycle); + + /** + * @brief 打开 PWM 通道并配置频率与占空比。 + * + * 这是一个便捷的函数,它首先尝试打开 PWM 通道,然后配置 PWM + * 信号的频率和占空比。 如果任何一步失败,函数将返回 false。 + * + * @param frequency PWM 信号的频率(Hz)。 + * @param duty_cycle PWM 信号的占空比(0.0 到 1.0 之间)。 + * @return bool 指示操作是否成功。 + */ + bool Open(uint32_t frequency, float duty_cycle); +}; +``` + +## 4 项目介绍 + +为了方便大家入手,我们做了一个简易的 PWM 例程。该例程可以输出持续 10s 的 PWM 信号。 + +```cmake +# CMake最低版本要求 +cmake_minimum_required(VERSION 3.10) + +project(test_pwm) + +# 定义项目根目录路径 +set(PROJECT_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../..") +# 定义 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) + +# 配置 PWM 读取例程 +add_executable(Test-PWM test_pwm.cc) +target_include_directories(Test-PWM PRIVATE ${LOCKZHINER_VISION_MODULE_INCLUDE_DIRS}) +target_link_libraries(Test-PWM PRIVATE ${LOCKZHINER_VISION_MODULE_LIBRARIES}) +``` + +例程的核心代码如下: + +```cpp +#include + +#include // 为了使用atoi() +#include // 为了使用strtof() +#include +#include + +int main(int argc, char* argv[]) { + uint32_t frequency = 1000000; + float duty_cycle = 0.5; + if (argc == 3) { + frequency = std::atoi(argv[1]); + duty_cycle = std::strtof(argv[2], nullptr); + } + std::cout << "frequency is " << frequency << std::endl; + std::cout << "duty_cycle is " << duty_cycle << std::endl; + + lockzhiner_vision_module::periphery::PWM pwm; + + // 打开 PWM + if (!pwm.Open(frequency, duty_cycle)) { + std::cout << "Failed to open adc." << std::endl; + return 1; + } + + for (int i = 0; i < 10; i++) { + std::cout << "Wait: " << i << "/" << 10 << std::endl; + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + // 关闭 PWM + if (!pwm.Close()) { + std::cout << "Failed to open adc." << std::endl; + return 1; + } + return 0; +} +``` + +## 5 编译项目 + +使用 Docker Destop 打开 LockzhinerVisionModule 容器并执行以下命令来编译项目 + +```bash +# 进入 Demo 目录 +cd /LockzhinerVisionModuleWorkSpace/LockzhinerVisionModule/example/periphery/pwm + +# 创建编译目录 +rm -rf build && mkdir build && cd build + +# 配置交叉编译工具链 +export TOOLCHAIN_ROOT_PATH=${PWD}/../../../../../arm-rockchip830-linux-uclibcgnueabihf + +# 使用 cmake 配置项目 +cmake -DCMAKE_TOOLCHAIN_FILE=../../../../toolchains/arm-rockchip830-linux-uclibcgnueabihf.toolchain.cmake \ + -DCMAKE_BUILD_TYPE=Release \ + .. + +# 执行编译 +make -j8 +``` + +![](images/build_example.png) + +## 6 正确连接设备 + +> 注意: Lockzhiner Vision Module PWM 引脚输出的理论高电平为 3.3V,理论低电平为 0V + +为了方便调试,我们这里使用 **示波器** 进行调试,请正确的将 Lockzhiner Vision Module 的引脚按照以下方式连接 + +* LockzhinerVisionModule PWM <-> Input IO +* LockzhinerVisionModule GND <-> Input GND + +板子上的引脚丝印较小,如果看不清引脚信息,可以参考下图 + +![](../../../images/periphery.png) + +## 7 执行 PWM 测试程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +使用 SFTP 功能将软件上传到 Lockzhiner Vision Module + +![](images/sftp.png) + +在 Lockzhiner Vision Module 上运行以下代码来执行 PWM 测试程序 + +```bash +chmod +x ./Test-PWM +# ./Test-PWM 频率(默认为1MHZ) 占空比(默认为0.5) +./Test-PWM 100000 0.5 +``` + +程序运行开始后,屏幕上打印配置的频率和占空比并开始每隔一秒显示当前进度 + +![](images/pwm_start.png) +![](../images/show_start.png) + +程序运行 10s 后,程序退出 PWM 停止 + +![](images/pwm_end.png) +![](../images/show_end.png) \ No newline at end of file diff --git a/example/periphery/pwm/images/build_example.png b/example/periphery/pwm/cpp/images/build_example.png similarity index 100% rename from example/periphery/pwm/images/build_example.png rename to example/periphery/pwm/cpp/images/build_example.png diff --git a/example/periphery/pwm/images/pwm_end.png b/example/periphery/pwm/cpp/images/pwm_end.png similarity index 100% rename from example/periphery/pwm/images/pwm_end.png rename to example/periphery/pwm/cpp/images/pwm_end.png diff --git a/example/periphery/pwm/images/pwm_start.png b/example/periphery/pwm/cpp/images/pwm_start.png similarity index 100% rename from example/periphery/pwm/images/pwm_start.png rename to example/periphery/pwm/cpp/images/pwm_start.png diff --git a/example/periphery/pwm/images/sftp.png b/example/periphery/pwm/cpp/images/sftp.png similarity index 100% rename from example/periphery/pwm/images/sftp.png rename to example/periphery/pwm/cpp/images/sftp.png diff --git a/example/periphery/pwm/test_pwm.cc b/example/periphery/pwm/cpp/test_pwm.cc similarity index 100% rename from example/periphery/pwm/test_pwm.cc rename to example/periphery/pwm/cpp/test_pwm.cc diff --git a/example/periphery/pwm/python/README.md b/example/periphery/pwm/python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a22a7a62af141bbd80c4f384d55d8be33c23f4d6 --- /dev/null +++ b/example/periphery/pwm/python/README.md @@ -0,0 +1,140 @@ +

凌智视觉模块 PWM Python 部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-26 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/26 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +接下来让我们基于 Python 来部署 PWM 例程。在开始本章节前: + +- 请确保你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 +- 请确保你已经按照 [凌智视觉模块 PWM 使用指南](../README.md) 正确将信号连接到开发板。 + +## 2 API 文档 + +```python +class PWMBase: + """ + @class PWMBase + @brief PWM 基础类,用于管理 PWM 设备的初始化和基本操作。 + + 此类提供了一个接口来配置、打开和关闭 PWM 设备。它依赖于一个具体的 PWM 类实例来实现这些操作。 + """ + + def __init__(self, pwm_class): + """ + @fn __init__(self, pwm_class) + @brief 构造函数, 初始化 PWMBase 对象。 + + @param pwm_class 一个 PWM 类,用于实际的 PWM 设备操作。 + """ + self.pwm = pwm_class() + + def config(self, frequency, duty_cycle): + """ + @fn config(self, frequency, duty_cycle) + @brief 配置 PWM 信号的频率和占空比。 + + @param frequency PWM 信号的频率。 + @param duty_cycle PWM 信号的占空比。 + + @return 配置操作的结果,通常由具体的 PWM 类决定。 + """ + return self.pwm.config(frequency, duty_cycle) + + def open(self): + """ + @fn open(self) + @brief 打开 PWM 设备,不指定频率和占空比(使用默认设置)。 + + @return 打开操作的结果,通常由具体的 PWM 类决定。 + """ + return self.pwm.open() + + def close(self): + """ + @fn close(self) + @brief 关闭 PWM 设备。 + + @return 关闭操作的结果,通常由具体的 PWM 类决定。 + """ + return self.pwm.close() + + +class PWM9(PWMBase): + def __init__(self): + super().__init__(periphery.PWM9) +``` + +## 3 项目介绍 + +为了方便大家入手,我们准备了 PWM 使用的最小例程,执行程序后 PWM 引脚将输出 10s 的 PWM 波形,代码如下: + +```python +from lockzhiner_vision_module.periphery import PWM9 +import time + + +if __name__ == "__main__": + pwm = PWM9() + pwm.config(1000000, 0.5) + pwm.open() + + time_index = 0 + total_time = 10 + while time_index < total_time: + print(f"Wait: {time_index}/{total_time}") + time_index += 1 + time.sleep(1) + + pwm.close() +``` + +## 4 执行 PWM 测试程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +使用 SFTP 功能将软件上传到 Lockzhiner Vision Module + +![](images/sftp.png) + +在 Lockzhiner Vision Module 上运行以下代码来执行 PWM 测试程序 + +```bash +python test_pwm.py +``` + +程序运行开始后,屏幕上打印配置的频率和占空比并开始每隔一秒显示当前进度 +![](images/pwm_start.png) +![](../images/show_start.png) + +程序运行 10s 后,程序退出 PWM 停止 + +![](images/pwm_end.png) +![](../images/show_end.png) \ No newline at end of file diff --git a/example/periphery/pwm/python/images/pwm_end.png b/example/periphery/pwm/python/images/pwm_end.png new file mode 100644 index 0000000000000000000000000000000000000000..546c0961e60dbf83ab4cf72f1cf0bed384a8d025 Binary files /dev/null and b/example/periphery/pwm/python/images/pwm_end.png differ diff --git a/example/periphery/pwm/python/images/pwm_start.png b/example/periphery/pwm/python/images/pwm_start.png new file mode 100644 index 0000000000000000000000000000000000000000..52eae3edaba5520b7cacdb1e917c10aaa61176fc Binary files /dev/null and b/example/periphery/pwm/python/images/pwm_start.png differ diff --git a/example/periphery/pwm/python/images/sftp.png b/example/periphery/pwm/python/images/sftp.png new file mode 100644 index 0000000000000000000000000000000000000000..debf4b83e1b69068a41da4bcd7ec8ad66b1d505b Binary files /dev/null and b/example/periphery/pwm/python/images/sftp.png differ diff --git a/example/periphery/pwm/python/test_pwm.py b/example/periphery/pwm/python/test_pwm.py new file mode 100644 index 0000000000000000000000000000000000000000..785f5dbbfbea1d4ad93027a170818c7a417b6993 --- /dev/null +++ b/example/periphery/pwm/python/test_pwm.py @@ -0,0 +1,17 @@ +from lockzhiner_vision_module.periphery import PWM9 +import time + + +if __name__ == "__main__": + pwm = PWM9() + pwm.config(1000000, 0.5) + pwm.open() + + time_index = 0 + total_time = 10 + while time_index < total_time: + print(f"Wait: {time_index}/{total_time}") + time_index += 1 + time.sleep(1) + + pwm.close() diff --git a/example/periphery/usart/README.md b/example/periphery/usart/README.md index bd0f7e7e06e730b2a5a7eda402c3ea049a2257d4..1091fc382f261f9b6c6140a7bcb3db9da8e055a8 100644 --- a/example/periphery/usart/README.md +++ b/example/periphery/usart/README.md @@ -35,7 +35,7 @@ ## 2 正确连接设备 -为了方便调试,我们这里使用 **CH340 USB 转串口模块(以下简称 CH340)**进行调试,请正确的将模型的引脚按照以下方式连接 +为了方便调试,我们这里使用 **CH340 USB 转串口模块(以下简称 CH340)** 进行调试,请正确的将模型的引脚按照以下方式连接 * LockzhinerVisionModule RX1 <-> CH340 TXD * LockzhinerVisionModule TX1 <-> CH340 RXD @@ -43,13 +43,17 @@ > Lockzhiner 也提供官方的 [CH340 USB 转串口模块](http://e.tb.cn/h.gMbjEDBRiaOutkO?tk=kBlS35jFQOE),如果有需要可以前往购买。 +板子上的引脚丝印较小,如果看不清引脚信息,可以参考下图 + +![](../../../images/periphery.png) + 打开串口工具,我这里选择的是 [vofa+](https://www.vofa.plus/),配置波特率为 115200 并打开串口 ![](images/vofa.png) ## 3 在凌智视觉模块上部署串口例程 -请参考以下教程使用 C++ 或 Python 在凌智视觉模块上部署串口例程: +请参考以下教程在凌智视觉模块上部署串口例程: -- [凌智视觉模块串口 C++ 部署指南](./cpp/README.md) + - [凌智视觉模块串口 Python 部署指南](./python/README.md) \ No newline at end of file diff --git a/example/periphery/usart/python/README.md b/example/periphery/usart/python/README.md index ea70cafd406bd3cb374b486bea0bfbc17494762b..dd87600a777992a944d2aad6c4ca0c1751573b64 100644 --- a/example/periphery/usart/python/README.md +++ b/example/periphery/usart/python/README.md @@ -30,14 +30,14 @@ ## 1 简介 -串口,也称为串行接口或串行通信接口,是一种用于连接计算机与外部设备并进行数据传输的接口技术。它使用较少的导线(通常只需要几根线),并且可以在较长的距离上可靠地传输数据,尽管速度相对较慢。本章节中,我们将教会你如何使用 Lockzhiner Vision Module 上的串口进行传输数据。 +串口,也称为串行接口或串行通信接口,是一种用于连接计算机与外部设备并进行数据传输的接口技术。它使用较少的导线(通常只需要几根线),并且可以在较长的距离上可靠地进行数据传输。本章节中,我们将教会你如何使用 Lockzhiner Vision Module 上的串口进行传输数据。 ## 2 前期准备 -接下来让我们基于串口来部署 GPIO 例程。在开始本章节前: +接下来让我们基于 Python 来部署串口例程,在开始本章节前: - 在开始这个章节前,请确保你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 -- 请确保你已经按照 [凌智视觉模块 GPIO 使用指南](../README.md) 正确将信号连接到开发板并打开了串口工具。 +- 请确保你已经按照 [凌智视觉模块串口使用指南](../README.md) 正确将信号连接到开发板并打开了串口工具。 ## 3 API 文档 diff --git a/example/special/digit_handwritten_recognition/README.md b/example/special/digit_handwritten_recognition/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b51eada0664734a3905ae465963b3a4a00d05c84 --- /dev/null +++ b/example/special/digit_handwritten_recognition/README.md @@ -0,0 +1,50 @@ +

凌智视觉模块手写数字识别部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-26 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/26 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +手写数字识别是经常使用到的功能之一。竞品 K210 和 OpenMV 提供了 Mnist 数字识别的案例,但是这些案例基于非真实环境的数据集,因此没办法直接在真实环境中使用,为了解决这个问题,我们基于 [凌智视觉模块分类模型部署指南](../../vision/classification) 训练了凌智视觉模块专用的模型,可以实现实时的数字识别功能。 + +## 2 运行前的准备 + +- 请确保你已经下载了 [凌智视觉模块手写数字识别模型](https://gitee.com/LockzhinerAI/LockzhinerVisionModule/releases/download/v0.0.0/LZ-DigitHandRecog.rknn) + +## 3 在凌智视觉模块上部署手写数字识别案例 + +下载模型后,请参考以下教程使用 Python 在凌智视觉模块上部署分类模型例程: + +- [凌智视觉模块手写数字识别 Python 部署指南](./python) + +## 4 模型性能指标 + +以下测试数据为模型执行 Predict 函数运行 1000 次耗时的平均时间 + +| 分类模型 | FPS(帧/s) | 精度(%) | +|:-------:|:----:|:----:| +|LZ-DigitHandRecog|35|96.74| diff --git a/example/special/digit_handwritten_recognition/python/README.md b/example/special/digit_handwritten_recognition/python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ed91cfb76f062be9553aad609594ba55614f7d3c --- /dev/null +++ b/example/special/digit_handwritten_recognition/python/README.md @@ -0,0 +1,108 @@ +

凌智视觉模块手写数字识别 Python 部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-26 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/26 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +接下来让我们基于 Python 来部署手写数字识别案例,在开始本章节前: + +- 请确保你已经参考 [凌智视觉模块手写数字识别部署指南](../README.md) 正确下载了模型。 +- 请确保你已经参考 [凌智视觉模块摄像头部署指南](../../../periphery/capture/README.md) 正确下载了凌智视觉模块图片传输助手。 +- 请确保你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 + +## 2 Python API 文档 + +同[分类模型 Python 部署 API 文档](../../../vision/classification/python/README.md) + +## 3 项目介绍 + +为了方便大家入手,我们做了一个简易的手写数字识别例程。该程序可以使用摄像头进行端到端推理,并可视化推理结果到凌智视觉模块图片传输助手。 + +```python +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import PaddleClas, visualize +from lockzhiner_vision_module.edit import Edit +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 2: + print("Need model path. Example: python test_digit_handwritten_rec.py LZ-DigitHandRecog.rknn") + exit(1) + + edit = Edit() + edit.start_and_accept_connection() + + model = PaddleClas() + if model.initialize(args[1]) is False: + print("Failed to initialize PaddleClas") + exit(1) + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + ret, mat = video_capture.read() + if ret is False: + continue + + result = model.predict(mat) + print(f"The label_id is {result.label_id} and the score is {result.score}") + + vis_mat = visualize(mat, result) + edit.print(vis_mat) +``` + +## 4 上传并测试 Python 程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +请使用 Electerm Sftp 依次上传以下两个文件: + +- 进入存放 **test_digit_handwritten_rec.py** 脚本文件的目录,将 **test_digit_handwritten_rec.py** 上传到 Lockzhiner Vision Module +- 进入存放 **LZ-DigitHandRecog.rknn** 模型存放的目录(模型存放在训练模型后下载的 output 文件夹内),将 **LZ-DigitHandRecog.rknn** 上传到 Lockzhiner Vision Module + +![](images/stfp.png) + +请使用 Electerm Ssh 并在命令行中执行以下命令: + +```bash +python test_digit_handwritten_recognition.py LZ-DigitHandRecog.rknn +``` + +运行程序后,使用凌智视觉模块图片传输助手连接设备,屏幕上开始打印标签索引和置信度,凌智视觉模块图片传输助手出现可视化的结果 + +![alt text](images/result_0.png) + + + + diff --git a/example/special/digit_handwritten_recognition/python/images/result_0.png b/example/special/digit_handwritten_recognition/python/images/result_0.png new file mode 100644 index 0000000000000000000000000000000000000000..c09e7e8b48da89ec1db2442a8bb9285c651d3c17 Binary files /dev/null and b/example/special/digit_handwritten_recognition/python/images/result_0.png differ diff --git a/example/special/digit_handwritten_recognition/python/images/stfp.png b/example/special/digit_handwritten_recognition/python/images/stfp.png new file mode 100644 index 0000000000000000000000000000000000000000..2f565d776585b7b7e905391eea48effb9c107848 Binary files /dev/null and b/example/special/digit_handwritten_recognition/python/images/stfp.png differ diff --git a/example/special/digit_handwritten_recognition/python/test_digit_handwritten_recognition.py b/example/special/digit_handwritten_recognition/python/test_digit_handwritten_recognition.py new file mode 100644 index 0000000000000000000000000000000000000000..531dfb2173daeec7b11492d5eb7182ddf62759ea --- /dev/null +++ b/example/special/digit_handwritten_recognition/python/test_digit_handwritten_recognition.py @@ -0,0 +1,36 @@ +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import PaddleClas, visualize +from lockzhiner_vision_module.edit import Edit +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 2: + print( + "Need model path. Example: python test_digit_handwritten_rec.py LZ-DigitHandRecog.rknn" + ) + exit(1) + + edit = Edit() + edit.start_and_accept_connection() + + model = PaddleClas() + if model.initialize(args[1]) is False: + print("Failed to initialize PaddleClas") + exit(1) + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + ret, mat = video_capture.read() + if ret is False: + continue + + result = model.predict(mat) + print(f"The label_id is {result.label_id} and the score is {result.score}") + + vis_mat = visualize(mat, result) + edit.print(vis_mat) diff --git a/example/special/qr_code_recognition/README.md b/example/special/qr_code_recognition/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3513b7338a8aed664f26c62fa16247dfa49b3691 --- /dev/null +++ b/example/special/qr_code_recognition/README.md @@ -0,0 +1,46 @@ +

凌智视觉模块二维码识别部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-27 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/27 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +二维码(QR Code)是一种二维条形码,因其高效的编码和解码能力而得名。二维码识别是视觉模块经常使用到的功能之一,本章节中,我们将教会你如何使用 Lockzhiner Vision Module 进行二维码识别。 + +## 2 在凌智视觉模块上部署二维码识别案例 + +下载模型后,请参考以下教程使用 Python 在凌智视觉模块上部署分类模型例程: + +- [凌智视觉模块二维码识别 Python 部署指南](./python) + +## 4 模型性能指标 + +以下测试数据为模型执行 Predict 函数运行 1000 次耗时的平均时间 + +| 分类模型 | FPS(帧/s) | 精度(%) | +|:-------:|:----:|:----:| +|LZ-DigitHandRecog|35|96.74| diff --git a/example/special/qr_code_recognition/python/README.md b/example/special/qr_code_recognition/python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1c3c879575170ed8cc430367a3caf13778dd2001 --- /dev/null +++ b/example/special/qr_code_recognition/python/README.md @@ -0,0 +1,210 @@ +

凌智视觉模块二维码识别 Python 部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-27 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/27 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +接下来让我们基于 Python 来部署二维码识别案例,在开始本章节前: + +- 请确保你已经参考 [凌智视觉模块摄像头部署指南](../../../periphery/capture/README.md) 正确下载了凌智视觉模块图片传输助手。 +- 请确保你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 + +## 2 Python API 文档 + +```python +class Point: + def __init__(self): + self.point = cv2.Point() + + @property + def x(self): + """ + 获取矩形左上角坐标点的 x 坐标 + + Returns: + int: 获取矩形左上角坐标点的 x 坐标 + """ + return self.rect.x + + @property + def y(self): + """ + 获取矩形左上角坐标点的 y 坐标 + + Returns: + int: 获取矩形左上角坐标点的 y 坐标 + """ + return self.rect.y + +class QRCodeResult: + """ + 二维码识别检测结果类,用于封装和处理二维码识别结果数据。 + + 该类主要提供了一个包装层,用于访问和管理由视觉模块产生的二维码识别结果。 + """ + + def __init__(self): + self.qr_code_result = vision.QRCodeResult() + + @property + def top_left(self): + """ + 获取二维码识别结果的左上角坐标 + + Returns: + Point: 左上角坐标 + """ + return self.qr_code_result.top_left + + @property + def top_right(self): + """ + 获取二维码识别结果的右上角坐标 + + Returns: + Point: 右上角坐标 + """ + return self.qr_code_result.top_right + + @property + def bottom_left(self): + """ + 获取二维码识别结果的左下角坐标 + + Returns: + Point: 左下角坐标 + """ + return self.qr_code_result.bottom_left + + @property + def bottom_right(self): + """ + 获取二维码识别结果的右下角坐标 + + Returns: + Point: 右下角坐标 + """ + return self.qr_code_result.bottom_right + + @property + def text(self): + """ + 获取二维码识别结果的文本数据 + + Returns: + Point: 二维码识别结果的文本数据 + """ + return self.qr_code_result.text + +class QRCodeDetector: + """ + QRCodeDetector 类 - 用于二维码识别的封装类。 + """ + def __init__(self): + self.model = vision.QRCodeDetector() + + def predict(self, input_mat): + """ + 进行预测 + + Args: + input_mat (cv2.Mat): 输入的图像数据,通常是一个 cv2.Mat 变量。 + + Returns: + list(QRCodeResult): 预测结果对象列表,每一个预测结果包含了二维码坐标和文本。 + """ + return self.model.predict(input_mat) +``` + +## 3 项目介绍 + +为了方便大家入手,我们做了一个简易的手写数字识别例程。该程序可以使用摄像头进行端到端推理,并可视化推理结果到凌智视觉模块图片传输助手。 + +```python +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import QRCodeDetector, visualize +from lockzhiner_vision_module.edit import Edit +import sys + +if __name__ == "__main__": + edit = Edit() + edit.start_and_accept_connection() + + model = QRCodeDetector() + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + ret, mat = video_capture.read() + if ret is False: + continue + + results = model.predict(mat) + print(f"result size is {len(results)}") + for result in results: + top_left = result.top_left + top_right = result.top_right + bottom_left = result.bottom_left + bottom_right = result.bottom_right + text = result.text + print( + f"(top_left,top_right,bottom_left,bottom_right,text): [({top_left.x}),{top_left.y}),({top_right.x}),{top_right.y}),({bottom_left.x}),{bottom_left.y}),({bottom_right.x}),{bottom_right.y}),{text}]" + ) + + vis_mat = visualize(mat, results) + edit.print(vis_mat) +``` + +## 4 上传并测试 Python 程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +请使用 Electerm Sftp 依次上传以下两个文件: + +- 进入存放 **test_qr_code_recognition.py** 脚本文件的目录,将 **test_qr_code_recognition.py** 上传到 Lockzhiner Vision Module + +![](images/stfp.png) + +请使用 Electerm Ssh 并在命令行中执行以下命令: + +```bash +python test_qr_code_recognition.py +``` + +运行程序后,使用凌智视觉模块图片传输助手连接设备,屏幕上开始打印二维码位置和置信度,凌智视觉模块图片传输助手出现可视化的结果 + +![alt text](images/qr_code_result.png) + + + + diff --git a/example/special/qr_code_recognition/python/images/2024_0927_10_10_00_267.png b/example/special/qr_code_recognition/python/images/2024_0927_10_10_00_267.png new file mode 100644 index 0000000000000000000000000000000000000000..3664906e5f8bfd128954841c863ac67056a72991 Binary files /dev/null and b/example/special/qr_code_recognition/python/images/2024_0927_10_10_00_267.png differ diff --git a/example/special/qr_code_recognition/python/images/qr_code_result.png b/example/special/qr_code_recognition/python/images/qr_code_result.png new file mode 100644 index 0000000000000000000000000000000000000000..4e12a63d4744590bb065ee668ad90ea00438a38e Binary files /dev/null and b/example/special/qr_code_recognition/python/images/qr_code_result.png differ diff --git a/example/special/qr_code_recognition/python/images/stfp.png b/example/special/qr_code_recognition/python/images/stfp.png new file mode 100644 index 0000000000000000000000000000000000000000..9c31239f4448987edcb4aede92c8e2ba6914727b Binary files /dev/null and b/example/special/qr_code_recognition/python/images/stfp.png differ diff --git a/example/special/qr_code_recognition/python/test_qr_code_recognition.py b/example/special/qr_code_recognition/python/test_qr_code_recognition.py new file mode 100644 index 0000000000000000000000000000000000000000..38496dc1cb054f083334f9ff63f53327c9544759 --- /dev/null +++ b/example/special/qr_code_recognition/python/test_qr_code_recognition.py @@ -0,0 +1,35 @@ +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import QRCodeDetector, visualize +from lockzhiner_vision_module.edit import Edit +import sys + +if __name__ == "__main__": + edit = Edit() + edit.start_and_accept_connection() + + model = QRCodeDetector() + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + ret, mat = video_capture.read() + if ret is False: + continue + + results = model.predict(mat) + print(f"result size is {len(results)}") + for result in results: + top_left = result.top_left + top_right = result.top_right + bottom_left = result.bottom_left + bottom_right = result.bottom_right + text = result.text + print( + f"(top_left,top_right,bottom_left,bottom_right,text): [({top_left.x}),{top_left.y}),({top_right.x}),{top_right.y}),({bottom_left.x}),{bottom_left.y}),({bottom_right.x}),{bottom_right.y}),{text}]" + ) + + vis_mat = visualize(mat, results) + edit.print(vis_mat) diff --git a/example/vision/classification/README.md b/example/vision/classification/README.md index 2959a30d91ded555c79cac05535f38d442b2c570..e1819f76ea16b27246779d69a70c17d625a8bf21 100644 --- a/example/vision/classification/README.md +++ b/example/vision/classification/README.md @@ -45,9 +45,13 @@ Labelme 是一个 python 语言编写,带有图形界面的图像标注软件 ![image-20240906175913060](images/download.png) +> 注: +> +> 如果网速太慢,我们也提供了百度网盘的下载链接,点击链接 [Labelme 标注工具(提取码:cyqc)](https://pan.baidu.com/s/1ssdBXxhoE1tME3nh-xqNzQ) 即可下载 + ### 2.2 标注前的准备 -首先,请参考 [摄像头使用指南](./example/periphery/capture/README.md) 利用 **Lockzhiner Vision Module 图片获取助手** 拍摄你需要进行标注的图片,如下图所示: +首先,请参考 [摄像头使用指南](./example/periphery/capture) 利用 **Lockzhiner Vision Module 图片获取助手** 拍摄你需要进行标注的图片,如下图所示: ![](images/capture_images.png) @@ -209,10 +213,10 @@ AI Studio 是基于百度深度学习开源平台飞桨的人工智能学习与 ## 4 在凌智视觉模块上部署模型 -训练完模型后,请参考以下教程使用 C++ 或 Python 在凌智视觉模块上部署分类模型例程: +训练完模型后,请参考以下教程在凌智视觉模块上部署分类模型例程: -* [凌智视觉模块分类模型 C++ 部署指南](./cpp/README.md) -* [凌智视觉模块分类模型 Python 部署指南](./python/README.md) + +- [凌智视觉模块分类模型 Python 部署指南](./python) ## 5 各模型性能指标 @@ -220,6 +224,4 @@ AI Studio 是基于百度深度学习开源平台飞桨的人工智能学习与 | 分类模型 | FPS(帧/s) | 精度(%) | |:-------:|:----:|:----:| -|LZ-MobileNetV2_x0_25|70.57|53.21| -|LZ-MobileNetV2_x0_5|63.48|65.03| -|LZ-MobileNetV2_x1_0|49.44|72.15| \ No newline at end of file +|LZ-MobileNetV3|40|75.32| diff --git a/example/vision/classification/python/README.md b/example/vision/classification/python/README.md index 708452d4333dcd50864dbc884e6a1cf2441195b4..cc88e73673ee16d02b8da20e5e88f08dd0746a25 100644 --- a/example/vision/classification/python/README.md +++ b/example/vision/classification/python/README.md @@ -64,14 +64,14 @@ class ClassificationResult: return self.classification_result.label_id @property - def confidence(self): + def score(self): """ 获取分类结果的标签 ID。 Returns: float: 分类结果的置信度,表示识别结果的可靠程度,范围为 0 到 1。 """ - return self.classification_result.confidence + return self.classification_result.score class PaddleClas: @@ -122,10 +122,16 @@ class PaddleClas: from lockzhiner_vision_module.cv2 import VideoCapture from lockzhiner_vision_module.vision import PaddleClas import time +import sys if __name__ == "__main__": + args = sys.argv + if len(args) != 2: + print("Need model path. Example: python test_classification.py LZ-MobileNetV3.rknn") + exit(1) + model = PaddleClas() - if model.initialize("LZ-MobileNetV2_x0_25.rknn") is False: + if model.initialize(args[1]) is False: print("Failed to initialize PaddleClas") exit(1) @@ -145,9 +151,9 @@ if __name__ == "__main__": start_time = time.time() result = model.predict(mat) end_time = time.time() - total_time_ms += (end_time - start_time) + total_time_ms += end_time - start_time read_index += 1 - print(result.label_id, result.confidence) + print(result.label_id, result.score) print(f"FPS is {1.0 / (total_time_ms/read_index)}") ``` @@ -159,8 +165,8 @@ if __name__ == "__main__": 请使用 Electerm Sftp 依次上传以下两个文件: -- 进入存放 **test_paddleclas.py** 脚本文件的目录,将 **test_paddleclas.py** 上传到 Lockzhiner Vision Module -- 进入存放 **LZ-MobileNetV2_x0_25.rknn(也可能是其他模型)** 模型存放的目录(模型存放在训练模型后下载的 output 文件夹内),将 **LZ-MobileNetV2_x0_25.rknn** 上传到 Lockzhiner Vision Module +- 进入存放 **test_classification.py** 脚本文件的目录,将 **test_classification.py** 上传到 Lockzhiner Vision Module +- 进入存放 **LZ-MobileNetV3.rknn** 模型存放的目录(模型存放在训练模型后下载的 output 文件夹内),将 **LZ-MobileNetV3.rknn** 上传到 Lockzhiner Vision Module ![](images/stfp_0.png) @@ -169,13 +175,13 @@ if __name__ == "__main__": 请使用 Electerm Ssh 并在命令行中执行以下命令: ```bash -python test_paddleclas.py LZ-MobileNetV3.rknn +python test_classification.py LZ-MobileNetV3.rknn ``` 运行程序后,屏幕上开始打印标签索引,分类置信度,并在一段时间后输出 FPS 值 -![alt text](result_0.png) +![alt text](images/result_0.png) -## 5 其他 + diff --git a/example/vision/classification/python/test_paddleclas.py b/example/vision/classification/python/test_classification.py similarity index 84% rename from example/vision/classification/python/test_paddleclas.py rename to example/vision/classification/python/test_classification.py index c24bf9063d414d06e145a6a6c91859499bbc9cd7..78a2fa0706f4d6870537531e632c2e7a5260c267 100644 --- a/example/vision/classification/python/test_paddleclas.py +++ b/example/vision/classification/python/test_classification.py @@ -6,7 +6,9 @@ import sys if __name__ == "__main__": args = sys.argv if len(args) != 2: - print("Need model path. Example: python test_paddleclas.py LZ-MobileNetV3.rknn") + print( + "Need model path. Example: python test_classification.py LZ-MobileNetV3.rknn" + ) exit(1) model = PaddleClas() @@ -23,14 +25,14 @@ if __name__ == "__main__": read_index = 0 total_time_ms = 0 for i in range(30): - start_time = time.time() ret, mat = video_capture.read() if ret is False: continue + start_time = time.time() result = model.predict(mat) end_time = time.time() total_time_ms += end_time - start_time read_index += 1 - print(result.label_id, result.confidence) + print(result.label_id, result.score) print(f"FPS is {1.0 / (total_time_ms/read_index)}") diff --git a/example/vision/detetcion/README.md b/example/vision/detetcion/README.md new file mode 100644 index 0000000000000000000000000000000000000000..122f68b782040a745e059a3fcf7c457f543f6a3b --- /dev/null +++ b/example/vision/detetcion/README.md @@ -0,0 +1,49 @@ +

凌智视觉模块检测模型部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-11 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/11 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +## 2 图像数据标注 + +## 3 使用 AIStudio 训练检测模型 + +## 4 在凌智视觉模块上部署模型 + +训练完模型后,请参考以下教程在凌智视觉模块上部署检测模型例程: + + +* [凌智视觉模块检测模型 Python 部署指南](./python/README.md) + +## 5 各模型性能指标 + +以下测试数据为模型执行 Predict 函数运行 1000 次耗时的平均时间 + +| 检测模型 | FPS(帧/s) | 精度(%) | +|:-------:|:----:|:----:| +|LZ-Picodet||| \ No newline at end of file diff --git a/example/vision/detetcion/python/README.md b/example/vision/detetcion/python/README.md new file mode 100644 index 0000000000000000000000000000000000000000..48c08afdde6b471a95fdd28868018e95cf2437c6 --- /dev/null +++ b/example/vision/detetcion/python/README.md @@ -0,0 +1,259 @@ +

凌智视觉模块检测模型 Python 部署指南

+ +发布版本:V0.0.0 + +日期:2024-09-11 + +文件密级:□绝密 □秘密 □内部资料 ■公开 + +--- + +**免责声明** + +本文档按**现状**提供,福州凌睿智捷电子有限公司(以下简称**本公司**)不对本文档中的任何陈述、信息和内容的准确性、可靠性、完整性、适销性、适用性及非侵权性提供任何明示或暗示的声明或保证。本文档仅作为使用指导的参考。 + +由于产品版本升级或其他原因,本文档可能在未经任何通知的情况下不定期更新或修改。 + +**读者对象** + +本教程适用于以下工程师: + +- 技术支持工程师 +- 软件开发工程师 + +**修订记录** + +| **日期** | **版本** | **作者** | **修改说明** | +| :--------- | -------- | -------- | ------------ | +| 2024/09/11 | 0.0.0 | 郑必城 | 初始版本 | + +## 1 简介 + +接下来让我们基于 Python 来部署 PaddleDetection 分类模型。在开始本章节前: + +- 请确保你已经参考 [凌智视觉模块检测模型部署指南](../README.md) 对模型进行了充分训练。 +- 请确保你已经按照 [开发环境搭建指南](../../../../docs/introductory_tutorial/python_development_environment.md) 正确配置了开发环境。 + +## 2 Python API 文档 + +```python +class Rect: + def __init__(self): + self.rect = cv2.Rect() + + def empty(self): + return self.rect.empty() + + @property + def x(self): + """ + 获取矩形左上角坐标点的 x 坐标 + + Returns: + int: 获取矩形左上角坐标点的 x 坐标 + """ + return self.rect.x + + @property + def y(self): + """ + 获取矩形左上角坐标点的 y 坐标 + + Returns: + int: 获取矩形左上角坐标点的 y 坐标 + """ + return self.rect.y + + @property + def width(self): + """ + 获取矩形的宽 + + Returns: + int: 获取矩形的宽 + """ + return self.rect.width + + @property + def height(self): + """ + 获取矩形的高 + + Returns: + int: 获取矩形的高 + """ + return self.rect.height + +class DetectionResult: + """ + 检测结果类,用于封装和处理目标检测结果数据。 + + 该类主要提供了一个包装层,用于访问和管理由视觉模块产生的检测结果。 + """ + + def __init__(self): + self.detection_result = vision.DetectionResult() + + @property + def box(self): + """ + 获取目标检测模型检测结果的矩形框信息 + + Returns: + Rect: 矩形框信息 + """ + return self.detection_result.box + + @property + def score(self): + """ + 获取目标检测模型检测结果的得分信息 + + Returns: + float: 得分信息 + """ + return self.detection_result.score + + @property + def label_id(self): + """ + 获取目标检测模型检测结果的分类标签信息 + + Returns: + int: 分类标签信息 + """ + return self.detection_result.label_id + +class PaddleDetection: + """ + PaddleDetection 类 - 用于目标检测的 PaddlePaddle 模型封装。 + + 该类封装了 PaddleDetection 框架下的目标检测模型,提供了初始化和预测的方法。 + """ + + def __init__(self): + """ + 构造函数 - 初始化 PaddleDetection 对象。 + """ + self.model = vision.PaddleDetection() + + def initialize(self, model_path): + """ + 初始化模型 - 加载预训练的 PaddlePaddle 模型。 + + Args: + model_path (str): 模型文件的路径。 + + Returns: + bool: 初始化是否成功。 + """ + return self.model.initialize(model_path) + + def set_threshold(self, score_threshold=0.5, nms_threshold=0.3): + """ + 设置目标检测阈值 + + Args: + score_threshold (float): 目标检测得分阈值,默认为 0.5 + nms_threshold (float): 目标检测 NMS 阈值,默认为 0.3 + + """ + self.model.initialize(score_threshold, nms_threshold) + + def predict(self, input_mat): + """ + 进行预测 - 使用加载的模型对输入数据进行分类预测。 + + Args: + input_mat (cv2.Mat): 输入的图像数据,通常是一个 cv2.Mat 变量。 + + Returns: + list(DetectionResult): 预测结果对象列表,每一个预测结果包含了分类的标签、置信度等信息。 + """ + return self.model.predict(input_mat) + + +class Picodet(PaddleDetection): + def __init__(self): + super().__init__() +``` + +## 3 项目介绍 + +为了方便大家入手,我们做了一个简易的图像分类例程。该程序可以使用摄像头进行端到端推理。 + +```python +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import PaddleDetection +import time +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 2: + print("Need model path. Example: python test_detection.py LZ-MobileNetV3.rknn") + exit(1) + + model = PaddleDetection() + if model.initialize(args[1]) is False: + print("Failed to initialize PaddleClas") + exit(1) + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + read_index = 0 + total_time_ms = 0 + for i in range(30): + ret, mat = video_capture.read() + if ret is False: + continue + + start_time = time.time() + results = model.predict(mat) + end_time = time.time() + total_time_ms += end_time - start_time + read_index += 1 + + print(f"result size is {len(results)}") + for result in results: + box = result.box + score = result.score + label_id = result.label_id + print( + f"(x,y,w,h,score,label_id): [{box.x},{box.y},{box.width},{box.height},{score},{label_id}]" + ) + print(f"FPS is {1.0 / (total_time_ms/read_index)}") +``` + +## 4 上传并测试 Python 程序 + +参考 [连接设备指南](../../../../docs/introductory_tutorial/connect_device_using_ssh.md) 正确连接 Lockzhiner Vision Module 设备。 + +![](../../../../docs/introductory_tutorial/images/connect_device_using_ssh/ssh_success.png) + +请使用 Electerm Sftp 依次上传以下两个文件: + +- 进入存放 **test_paddleclas.py** 脚本文件的目录,将 **test_paddleclas.py** 上传到 Lockzhiner Vision Module +- 进入存放 **LZ-MobileNetV2_x0_25.rknn(也可能是其他模型)** 模型存放的目录(模型存放在训练模型后下载的 output 文件夹内),将 **LZ-MobileNetV2_x0_25.rknn** 上传到 Lockzhiner Vision Module + +![](images/stfp_0.png) + +![](images/stfp_1.png) + +请使用 Electerm Ssh 并在命令行中执行以下命令: + +```bash +python test_paddleclas.py LZ-MobileNetV3.rknn +``` + +运行程序后,屏幕上开始打印标签索引,分类置信度,并在一段时间后输出 FPS 值 + +![alt text](result_0.png) + +## 5 其他 + +如果你需要使用 C++ 来部署 PaddleClas 请参考[凌智视觉模块分类模型 C++ 部署指南](../cpp/README.md)。 diff --git a/example/vision/detetcion/python/test_detection.py b/example/vision/detetcion/python/test_detection.py new file mode 100644 index 0000000000000000000000000000000000000000..0e9d47d7a8e4c87753707a574573f63ab471af2f --- /dev/null +++ b/example/vision/detetcion/python/test_detection.py @@ -0,0 +1,44 @@ +from lockzhiner_vision_module.cv2 import VideoCapture +from lockzhiner_vision_module.vision import PaddleDetection +import time +import sys + +if __name__ == "__main__": + args = sys.argv + if len(args) != 2: + print("Need model path. Example: python test_detection.py LZ-MobileNetV3.rknn") + exit(1) + + model = PaddleDetection() + if model.initialize(args[1]) is False: + print("Failed to initialize PaddleClas") + exit(1) + + video_capture = VideoCapture() + if video_capture.open(0) is False: + print("Failed to open capture") + exit(1) + + while True: + read_index = 0 + total_time_ms = 0 + for i in range(30): + ret, mat = video_capture.read() + if ret is False: + continue + + start_time = time.time() + results = model.predict(mat) + end_time = time.time() + total_time_ms += end_time - start_time + read_index += 1 + + print(f"result size is {len(results)}") + for result in results: + box = result.box + score = result.score + label_id = result.label_id + print( + f"(x,y,w,h,score,label_id): [{box.x},{box.y},{box.width},{box.height},{score},{label_id}]" + ) + print(f"FPS is {1.0 / (total_time_ms/read_index)}") diff --git a/images/pp.png b/images/pp.png new file mode 100644 index 0000000000000000000000000000000000000000..9d728e1f1f661fe9161e72f62e22dfbdf99e352a Binary files /dev/null and b/images/pp.png differ