TA的每日心情 | 开心 2020-10-13 14:25 |
|---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
童生
- 积分
- 134

|
Renesas RA8 系列(如 RA8M1/RA8D1)是瑞萨面向高端嵌入式场景的 MCU,部署仪表识别算法需结合硬件特性、算法轻量化、工具链适配三大核心环节。
一、RA8 系列核心特性RA8 :
CPU:Arm Cortex-M85(最高 480MHz,支持 ARMv8-M 架构、DSP 指令、M-Profile Vector Extension (MVE) 向量扩展);
AI加速器:集成 CNN 加速器(RA8D1),支持轻量化神经网络推理;
外设:支持摄像头(CSI/DSI)、LCD 屏、DMA、硬件浮点单元(FPU)
仪表识别算法通常包含:图像采集→预处理→数字 / 指针识别→结果输出,RA8 可兼顾传统机器视觉(如 OpenCV-Micro)和轻量化 CNN(如 TensorFlow Lite Micro)两种方案。
二、部署步骤,开发环境搭建安装工具链 OpenCV
2.1 下载并安装瑞萨 e² studio:https://www.renesas.com/cn/zh/software-tool/e-studio
2.2 安装 RA8 系列 FSP 包(包含底层驱动、中间件):在 e² studio 中通过FSP Installer安装对应型号的 FSP;
2.3 可选:安装 Arm GNU Toolchain(用于编译轻量化算法)、TensorFlow Lite Micro(TFLM)源码。
2.4 安装 RT-Thread Studio 详见官网,在SDK 管理器中下载 sdk-bsp-ra8p1-titan-board ,推荐离线导入SDK;
2.5 安装瑞萨 NPU 驱动组件:在 RT-Thread Studio 的RT-Thread Settings 中,启用 Renesas NPU 驱动、rtsl_ai 人工智能框架;
2.6 配置编译器:使用 ARM GCC 10.3 以上版本,开启 march=armv8.1-m.main+mve.fp -O3 优化(利用 MVE 向量指令加速预处理)。
三、数字仪表识别(无 NPU,轻量快速)
核心逻辑:图像预处理→轮廓检测→数字分割→模板匹配,基于 RT-Thread 的cv组件实现:
核心算法:
- <span style="color: rgb(0, 0, 0); font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre;">#include <opencv2/opencv.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
- #include <cmath>
- #include <iostream>
- using namespace cv;
- using namespace std;
- // 仪表参数配置(根据实际仪表调整)
- const float GAUGE_MIN_ANGLE = 45.0f; // 指针最小值对应角度(顺时针)
- const float GAUGE_MAX_ANGLE = 315.0f; // 指针最大值对应角度
- const float GAUGE_MIN_VALUE = 0.0f; // 仪表最小值
- const float GAUGE_MAX_VALUE = 100.0f; // 仪表最大值
- const int GAUGE_RADIUS = 150; // 表盘半径(像素)
- // 计算两点间角度
- float calculateAngle(Point center, Point point) {
- float dx = point.x - center.x;
- float dy = point.y - center.y;
- float angle = atan2(dy, dx) * 180.0f / CV_PI;
- if (angle < 0) angle += 360.0f;
- return angle;
- }
- // 角度转仪表数值
- float angleToValue(float angle) {
- // 角度范围映射到数值范围
- if (angle < GAUGE_MIN_ANGLE) angle += 360.0f;
- if (angle > GAUGE_MAX_ANGLE) angle = GAUGE_MAX_ANGLE;
-
- float ratio = (angle - GAUGE_MIN_ANGLE) / (GAUGE_MAX_ANGLE - GAUGE_MIN_ANGLE);
- return GAUGE_MIN_VALUE + ratio * (GAUGE_MAX_VALUE - GAUGE_MIN_VALUE);
- }
- int main() {
- // 1. 初始化摄像头(Titan Board 通常为 /dev/video0)
- VideoCapture cap(0);
- if (!cap.isOpened()) {
- cerr << "无法打开摄像头!" << endl;
- return -1;
- }
- // 降低分辨率,提升嵌入式性能
- cap.set(CAP_PROP_FRAME_WIDTH, 640);
- cap.set(CAP_PROP_FRAME_HEIGHT, 480);
- Mat frame, gray, blur, edges, mask;
- while (true) {
- // 2. 读取帧并预处理
- cap >> frame;
- if (frame.empty()) break;
- // 灰度化 + 高斯模糊(降噪)
- cvtColor(frame, gray, COLOR_BGR2GRAY);
- GaussianBlur(gray, blur, Size(5, 5), 1.5);
- // 边缘检测(Canny)
- Canny(blur, edges, 50, 150);
- // 3. 检测表盘轮廓(圆形检测)
- vector<Vec3f> circles;
- HoughCircles(blur, circles, HOUGH_GRADIENT, 1,
- blur.rows/8, 100, 30, 100, 200);
- if (!circles.empty()) {
- // 取最大的圆形作为表盘(避免多轮廓干扰)
- Vec3f largestCircle = circles[0];
- Point center(largestCircle[0], largestCircle[1]);
- int radius = largestCircle[2];
- // 绘制表盘轮廓
- circle(frame, center, radius, Scalar(0, 255, 0), 2);
- // 4. 检测指针(基于掩码提取指针区域)
- mask = Mat::zeros(gray.size(), CV_8UC1);
- circle(mask, center, radius-5, Scalar(255), -1); // 表盘掩码
- Mat masked_edges;
- bitwise_and(edges, mask, masked_edges);
- // 霍夫直线检测指针
- vector<Vec4i> lines;
- HoughLinesP(masked_edges, lines, 1, CV_PI/180, 50, 30, 10);
- if (!lines.empty()) {
- // 取最接近圆心的直线作为指针
- Vec4i bestLine = lines[0];
- Point p1(bestLine[0], bestLine[1]);
- Point p2(bestLine[2], bestLine[3]);
- // 计算指针端点(延长线到表盘边缘)
- Point pointerEnd;
- float dx = p2.x - p1.x;
- float dy = p2.y - p1.y;
- float len = sqrt(dx*dx + dy*dy);
- if (len > 0) {
- pointerEnd.x = center.x + (dx/len) * radius;
- pointerEnd.y = center.y + (dy/len) * radius;
- }
- // 绘制指针
- line(frame, center, pointerEnd, Scalar(0, 0, 255), 2);
- // 5. 计算角度和数值
- float angle = calculateAngle(center, pointerEnd);
- float value = angleToValue(angle);
- // 显示结果
- putText(frame, "Value: " + to_string(value), Point(20, 40),
- FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 0), 2);
- }
- }
- // 显示画面(Titan Board 需接显示屏,或注释改用串口输出)
- imshow("Gauge Recognition", frame);
- // 按ESC退出
- if (waitKey(1) == 27) break;
- }
- cap.release();
- destroyAllWindows();
- return 0;
- }</span>
复制代码 先拐个弯:测试RTT+LVGL 运行个demo
- /*
- * 前置条件:lv_conf.h中需启用以下字体(确保编译不优化掉)
- * #define LV_FONT_MONTSERRAT_20 1
- * #define LV_FONT_MONTSERRAT_24 1
- */
- static void lv_blessing_screen_create(void)
- {
- lv_obj_t * scr = lv_screen_active();
-
- /* 1. 设置红色背景(与非网品牌红) */
- lv_obj_set_style_bg_color(scr, lv_color_hex(0xC41E3A), LV_STATE_DEFAULT);
- lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, LV_STATE_DEFAULT);
- lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); // 禁止屏幕滚动
-
- /* 2. 第一行:Eefocus & Renesas*/
- lv_obj_t * label1 = lv_label_create(scr);
- lv_label_set_text(label1, "Eefocus & Renesas");
- lv_obj_set_style_text_color(label1, lv_color_white(), LV_STATE_DEFAULT);
- lv_obj_set_style_text_font(label1, &lv_font_montserrat_24, LV_STATE_DEFAULT);
- lv_obj_align(label1, LV_ALIGN_TOP_MID, -120, 10);
-
- /* 3. 第二行:Wishes all electronic engineers - */
- lv_obj_t * label2 = lv_label_create(scr);
- lv_label_set_text(label2, "Wishes all electronic engineers");
- lv_obj_set_style_text_color(label2, lv_color_white(), LV_STATE_DEFAULT);
- lv_obj_set_style_text_font(label2, &lv_font_montserrat_20, LV_STATE_DEFAULT);
- lv_obj_align(label2, LV_ALIGN_CENTER, -120, -140);
-
- /* 4. 第三行:Success in the Year of the Horse! - */
- lv_obj_t * label3 = lv_label_create(scr);
- lv_label_set_text(label3, "Success in the Year of the Horse!");
- lv_obj_set_style_text_color(label3, lv_color_hex(0xFFD700), LV_STATE_DEFAULT);
- lv_obj_set_style_text_font(label3, &lv_font_montserrat_20, LV_STATE_DEFAULT);
- lv_obj_align(label3, LV_ALIGN_CENTER, -120, -80);
-
- /* 5. 第四行:Happy New Year - 核心修复(相对第三行对齐,100%显示) */
- lv_obj_t * label4 = lv_label_create(scr);
- lv_label_set_text(label4, "Happy New Year");
- lv_obj_set_style_text_color(label4, lv_color_white(), LV_STATE_DEFAULT);
- lv_obj_set_style_text_font(label4, &lv_font_montserrat_20, LV_STATE_DEFAULT);
- // 关键改:基于第三行底部居中向下偏移80px,绕开屏幕底部边界问题
- // X轴保留-120,和前三行水平对齐
- lv_obj_align_to(label4, label3, LV_ALIGN_OUT_BOTTOM_MID, 0, 80);
- }
复制代码
祝工程师项目马到功成!
|
|