站内搜索
发作品签到
专业版

2025-C题国一-基于单目视觉的目标物测量装置

工程标签

3.0k
0
0
2

简介

亚像素拟合、PnP测距、实时测量、多点触控、三维重建……利用Flutter,我们将“前后端分离”引入了电赛。想“零成本复刻”吗?只需一部安卓手机!

简介:亚像素拟合、PnP测距、实时测量、多点触控、三维重建……利用Flutter,我们将“前后端分离”引入了电赛。想“零成本复刻”吗?只需一部安卓手机!
助力2025全国电赛

开源协议

GPL 3.0

(未经作者授权,禁止转载)
创建时间:2025-04-16 13:04:53更新时间:2025-09-16 14:36:42

描述

一、团队介绍

我们是来自华北电力大学的OpenCV钉子户,在2025全国大学生电子设计竞赛中获得全国一等奖。

二、题目要求

官方对题目的要求描述比较模糊,在看过测评实物后,概括起来就是:

题目要求的框图

首先需要搭建下图这样的场景:

题目中给出的场景示意图

其中目标物是用一张A4纸,贴外边缘向内画宽2cm的黑线,然后在里面放置这样几种图片,要求找到并测出其中边长或直径最小的矩形/圆形/三角形,或者指定序号的矩形的尺寸:

题目具体要求如下:

当然,既然是电赛,至少得有电路设计。所以题目还要求:“优化测量装置,降低整机功耗。要求测试全程实时监测并显示测量装置的功耗P和最大功耗Pmax ”,并且“自制图2中的供电电流测量电路时,不得使用商品模块”。

三、题目分析

这道题,可以说是一道纯视觉题。题目中的难点在于:

    • 如何测量到目标物的距离?
    • 如何识别重叠且旋转正方形?
    • 如何识别正方形中的数字?

3.1 目标物的识别

因为题目没有说明背景板样式,为了避免背景影响识别,也为了方便目标物的打印,我们只检测目标物的内侧边框

具体步骤是:图像转灰度->Canny边缘检测->轮廓检测->闭合多边形拟合提取全部面积足够大的四边形->找到左上角角点并顺时针排序。

在得到的所有四边形中,将角点向重心方向平移20像素,得到四个点,再判断这四个点是否全为黑色(避免误识别到外边框或识别到内部矩形的情况),最后在其中找到最大的候选项,进行后续操作。

3.2 单目测距

根据相似三角形原理,可以实现简单的测距,但我们的目标物有4个关键点,理论上还能得到更精确的信息,比如平移和旋转即PnP问题(Perspective-n-Point,多点透视)。OpenCV为我们提供了一个函数用来求解这类问题:cv2.solvePnP

图来自Medium

PnP算法原理比较复杂,但我们作为使用者,只需要知道:假设通过相机标定得到相机的内参(即:焦距和图像中点坐标)畸变数据,根据照片中几个点的坐标和它们在物体上的三维坐标,函数能自动求解出物体上各点到相机坐标系的映射,其中包括平移向量(物体原点在相机坐标系中的XYZ坐标)和旋转向量(物体坐标系到相机坐标系的旋转)。对于本题目,假设底边中点为物体原点,A4纸的短边向右为X轴,长边向下为Y轴。

那么如何得到相机内参和畸变呢?OpenCV同样提供了一个函数:cv2.calibrateCamera。只需输入大量图像中的角点和在实物(一般使用棋盘格)上对应点的相对坐标,可以自动计算出相机内参和畸变信息。

在通过PnP算法得到目标物的空间坐标后,如果直接用物体的平移向量作为距离D,因为相机在摆放时总会产生俯仰角误差,结果势必会受物体左右平移和旋转影响。我们采用的思路是:先在1250mm处放置参考目标物,测出它在相机系中的位姿,随后保持相机不动,测量待测目标物的位姿,平移向量相减,旋转矩阵相乘,可得到相对平移向量和相对旋转矩阵,再用参考目标物的旋转矩阵的逆与相对平移向量相乘,把它旋转到参考目标物的坐标系中,得到新向量取其Z分量,加上1250mm即为实际距离D。

由于参考目标物摆放时,Z轴是垂直于参考图中的“轴线”的,相对平移向量在参考目标物Z轴向量上的投影向量长度,加上参考目标物的实际位置,就是待测目标物的实际位置。之后只要相机位置固定,无论目标物如何平移、旋转,都不影响它底边中点在Z方向的投影等于题目要求的D,因为距离D的定义就是这个投影向量的长度:“目标物面标记点在基准面上的垂直投影点与基准线之间的距离”。

不过测评时发现:评委不让用尺子等工具测量任何距离,因此需要提前标定好后保持摄像头角度不变。我们的方法是直接把摄像头固定在亚克力板上,标定与测量时把亚克力板边缘对齐参考线。

3.3 逆透视变换

在进行下一步操作前,需要将目标物从图像中提取出来,方便后续计算和调试。透视变换就是把图像中的四个点,把它们“拉伸”到另外四个点的位置,同时保持透视关系。我们知道,矩阵可以用来描述变换,OpenCV的cv2.getPerspectiveTransform函数,就是用来计算这个变换矩阵的。以下图为例:传入右图4个角点和左图中的4个角点,这个函数可以自动计算出透视变换矩阵,随后通过cv2.warpPerspective将整张图片拉伸到左图。

为什么这里要强调透视变换是一个矩阵呢?因为两个矩阵相乘,可以把两次变换叠加成一次变换。因此,我们可以再构建一个仿射变换矩阵(仿射变换可以理解为平移+旋转+缩放+斜切,但是没有透视变换的近大远小),实现一次操作就能在透视裁切基础上向外扩展像素,而且不会影响图像比例。相关代码封装在easytrans.py中,只需要传入四个点和目标图像的分辨率、扩展像素数,函数可自动完成对角点排序,裁切出透视区域返回,减轻竞赛时的编码负担。

我们在实际操作时,将内部区域统一成850*1285像素的图像(即(210mm-20mm*2, 297mm-20mm*2)*5),使得图像中5像素对应实物1毫米,便于后续测量图形尺寸。

图片包含 图示

AI 生成的内容可能不正确。图标

AI 生成的内容可能不正确。

3.4 简单形状的识别

题目中最简单的形状是等边三角形:直接提取轮廓、拟合封闭多边形,找到边长等于3且三边近似相等的最大三边形即可。

对于圆形,一般采用霍夫圆算法检测。但对于这类背景空白,且对精度要求高的场景,我们采用“圆度”——4*PI*面积/周长^2。这个值大于0.8时,可认为这是一个圆。这种方法相比霍夫圆而言,识别到的圆不会抖动,尺寸精度相对更高。

3.5 多正方形的识别

这道题最复杂的部分在于多个重叠正方形的识别,可以分为以下几点。

前提:图像中只有正方形。下文中“直角点”意为内直角点,“角点”意为轮廓的全部转角,除直角点外还包括大于180度的角和白色孔洞中的角点。

确定图像中的全部正方形,至少需要:

    • 1个直角点和它的对边
    • 4条两两垂直的边

为加快算法运行速度,优先考虑:

    • 1对直接相邻直角点
    • 1对直角边相互垂直的直角点

所以最终算法流程:

    • 检测直接相邻直角点
    • 剩余直角点中,两两组合,找到相对直角点
    • 剩余边中,任意四边组合,找到两两垂直的边线,且延长后能组成正方形
    • 剩余直角点中,与剩余边组合,找到可能的对边

因为约束条件太少,这些候选正方形中有很多误识别的情况,因此还需要把不是正方形的部分排除。图像中的正方形,一定满足以下条件:

    • 四边相等
    • 四个角等于90度
    • 内部不包含孔洞或角点(因为正方形是实心的,如果有孔洞会被盖住。白色数字区域除外)
    • 边长大于40mm(题目中最小边长60mm)

根据这些限制条件,基本可以确找到全部正方形。具体原理可见开源代码中task_multi_rectangles.py。

3.6 数字识别

数字识别的方案有很多,如Hu矩、KNN、CNN、OCR等,我们采用一个简单的CNN网络,在24*24的灰度图像上训练了一个分类器模型,实测在黑体和衬线体均能达到99%正确率。

四、算法优化与创新

4.1 亚像素角点拟合

亚像素角点拟合是一种在图像处理中用于提高角点检测精度的方法。常规角点检测通常只能在像素级定位角点位置,而在C题这种需要高精度测量的场合,像素级精度往往不足。通过亚像素角点拟合算法,可以在检测到的初始角点附近,对灰度分布进行最小二乘迭代,将角点位置精确到小数像素级别。这不仅显著提升了特征点的定位精度,还能有效减少后续几何计算中的累计误差,是高精度计算机视觉任务中的关键步骤。同样的,OpenCV提供了一个函数用于在指定范围内拟合角点:cv2.cornerSubPix

图片包含 图形用户界面

AI 生成的内容可能不正确。

拟合前(红)和拟合后(绿),近邻采样放大20倍

在我们的作品中,在目标物定位、矩形检测时,因为cv2.approxPolyDP、求边线交点时会丢失一定精度,导致识别框抖动,因此在进行透视变换前,应用这一算法获得四角点的浮点数坐标,在所有正方形识别完成后,将它们的顶点在一定半径内,靠拢到外轮廓上经过拟合的角点上,通过这一系列操作,配合4K工业相机,使得我们的正方形尺寸误差做到了0.5毫米以内,距离误差在摄像头不受扰动的前提下,做到2毫米以内

4.2 用代码测试代码

由于组委会没有给出全部测试用例,人工测试无法穷举所有可能的场景,单纯依赖人工摆放目标物并逐一测量,不仅效率低下,而且容易遗漏边界情况。特别是在多矩形识别任务中,任意一处对原有算法(如最小多边形约束条件、角点拟合区域)的修改,或是新算法的添加(如直角点-对边识别算法的添加),都会潜在影响整体识别的准确率,甚至导致其它矩形目标的检测结果发生偏差。

为此,我们借助程序模拟经过逆透视变换的目标物灰度图像,自动化调用多正方形识别模块,并检查记录识别错误率和失误率,保证在算法迭代过程中整体识别稳定性。相比于手工测量不到5 SPF的速度而言,程序能以约每秒50帧(250个正方形)的速度测试,并且可以在出现失误或错误时自动暂停,以便对这种特殊情况进行分析与优化。虽然程序会生成出不具有唯一解的图像,每次生成的图像也不尽相同,但在样本数量足够大时,错误率与失误率会收敛到一个固定值,在代码优化遇到瓶颈时,这个值便可以用来量化算法的好坏。

比如,在实现“单角点-对边”这一条件下的正方形检测算法后,虽然代码只有不到40行:

文本

AI 生成的内容可能不正确。

但在经过30000个正方形(3分钟)的测试后,虽然错误率略有升高,但它将失误率降低了一倍,基本识别出了所有存在唯一解的正方形:

形状

AI 生成的内容可能不正确。

又比如,在过滤白色孔洞时,在原本面积/边数判断基础上,添加一条规则:“白色孔洞面积大于1000且边数小于等于3”。修改后代码长这样:

这个看似不起眼的规则,在经过约20000个正方形测试后,修改后的代码在错误率几乎不变的前提下,失误率降低了0.65%

因为组委会没有提供目标物示例图,在作品制作后期,我们采用在保持错误率不升高的前提下尽可能降低失误率的策略,尽最大可能调节优化算法参数,力求识别出全部可能的重叠正方形。

4.3 前后端分离开发

相信大家比赛时一定有过这样的感受:移植队友的代码所需的时间,比重新写一遍还要多

有没有一种办法,把界面和算法分开呢?这样只需要开始时约定好通信规则,然后分别独立开发,最终集成时,只要保证通信协议一致,就能无缝衔接。这便是前后端分离的思想。

帮助我们实现前后端分离思想的,是Flutter这一跨平台UI开发框架。

在开发过程中,Dart语言的热重载(Hot Reload)功能为我们带来了极大的便利。热重载可以在代码修改后,按下保存就能将代码修改应用到正在运行的程序中,同时保留程序上下文,而无需重新编译整个应用。比如在调整UI样式、修改交互逻辑时,只需保存代码,界面就会立即刷新并体现改动效果,甚至不影响变量值

相比于去年省赛我们用的LVGL、隔壁队伍用的Qt、tkinter,Flutter 的优势尤其适合竞赛场景:它的开发过程更直观,UI 修改所见即所得;同时拥有丰富的第三方库支持,常见功能无需重复造轮子;在前后端通信中,只需一行代码即可完成 JSON 的序列化与反序列化,极大方便了通信协议的数据处理;其内置的 async/await 异步机制还能避免耗时任务阻塞 UI,确保界面始终保持流畅响应;Flutter 的渲染引擎采用GPU 加速(OpenGL ES),为运行在CPU上的视觉算法和数据处理节省更多计算资源。依托这些特性,我们能够把更多精力投入到算法和功能创新上,而不是底层细节的重复开发,从而在有限的竞赛时间里快速产出高质量的作品

但是,作为一个前端框架,Flutter也存在一些局限性:对本地资源访问限制较多,并且许多库不支持flutter-pi(一个把Flutter移植到无X窗口管理器的嵌入式Linux平台的开源项目),最关键的一点是:flutter-pi占用了整个帧缓冲区,导致Python无法实时将运行结果推送到显示屏。

为了解决这一问题,我们在几个月前专门为flutter-pi项目开发了一个插件,可以将任意numpy图像数组(比如opencv或matplotlib产生的图像)通过Linux的共享内存机制发送到flutter-pi进程,flutter-pi插件的C语言部分在收到信号后,直接把这块内存区域上传到GPU,剩余绘制操作交由Dart渲染器完成。由于C语言与Dart语言之间只传递了一个4字节整形变量,对性能几乎没有影响。赛前实测在RK3566(比如立创“泰山派”)上,640*640分辨率读取USB摄像头,运行yolov5s并实时显示推理结果(640*480@25 FPS)的场景下,CPU占用不到25%.

通过htop查看CPU与内存占用率

并且由于是GPU渲染,任意缩放图像也不会掉帧。

至于跨语言通信,我们没有使用Protobuf这类成熟的方案,而是为电赛量身定制了一个基于JSON和TCP的类RPC通信协议,称之为LVIOP (LiVision Inter Operation)。这一框架在各处细节都为电赛场景下有限时间内的快速开发而设计,它有这些优势:

    • 自适应主从设备:避免通信算法耽误时间
    • 函数无需提前声明:降低学习成本
    • 断线自动重连、自动捕获异常:避免未发现的报错导致比赛时程序崩溃
    • 支持绑定闭包:作用域内的变量,能看到就能用

但它有一个缺陷:不支持函数返回值。不过这一点可以通过回调的形式间接解决。

你问我LiVision是什么?是一个专为电赛设计的RK3566开发板,今年年底开源~

在我们的作品设计中,一共约定了25个函数,在用户进行对应操作后,前端调用这些函数通知后端,后端将结果通过8个函数反馈给前端。基于这一架构,前端可以随意改变UI设计,优化用户体验,而无需关心后端的代码。后端在优化算法后,也不需要与前端沟通。这大大加速了我们的开发进度。

4.4 3D姿态可视化

作为一个使用GPU绘图的框架,当然可以做3D渲染。之前的算法中,我们拿到了目标物的相对位移和相对旋转,基于此我们实现了一个发挥功能:将目标物的三维旋转通过3D模型(这里用的我的世界物品展示框模型)实时展示出来。Flutter有一个开源包flutter_cube,刚好可以实现这个需求,可惜原版不更新了,有一些Bug,比如对模型面片数量要求较高、多Object时不能正确显示纹理,好在几月前用Flutter制作MPU6050的姿态可视化程序时用过这个库,直接把代码复制过来,只用了不到半小时就完成了。

实际开发过程中,受到主控性能限制,我们采取暂时降低相机分辨率,调小目标物识别参数,以降低精度为代价换来了更低的延迟,尽量保证了3D重建的实时性

五、总体设计框图

六、硬件电路组成

这道题的硬件部分相对比较简单,用INA226配合采样电阻测量输入电流,再用STM32读取并用u8g2图形库绘制在OLED屏幕上。屏幕是一年前一块钱捡的,0.96寸,但控制器是SH1106,如果是常见的SSD1306只需改一下初始化代码。

嵌入式开发板选择的是鲁班猫3(RK3576)。选择它的原因在于它有一个USB3.1接口,在连接4K USB摄像头时帧率更高,而且空闲功耗相对低一些。如果使用立创泰山派或其它开发板也能达到类似的效果。运行Linux系统的电脑,接一个USB摄像头也能正常运行。

七、实物展示

八、零成本复刻

随着电赛的结束,实验室招新也逐渐拉开序幕。

我们的作品中,用到了4K工业相机和嵌入式Linux核心板,成本较高。另外由于依赖库较多,Python环境搭建与调试对于大一新生也是一个挑战。如果作品无法被复刻,开源也就失去了意义。有没有办法,让每个人都能体验到我们开源的电赛作品呢?

纵观整个作品不难发现,硬件部分包括:

    • 高分辨率摄像头
    • 7寸屏幕
    • 电源管理

软件部分包括:

    • 前端Flutter
    • 用于图像处理的OpenCV
    • 用于数字识别的OnnxRuntime

工业摄像头价格都不便宜,但现在随便一部手机的摄像头分辨率都能达到千万像素,还支持测量实时功耗。能不能把整个算法移植到手机上呢?

理论上是可以的。

得益于前后端分离的设计,移植过程非常顺利,最大程度上保留了作品原本的操作逻辑和功能。由于手边没有iOS设备,因此我只对安卓手机进行了适配,大家可以访问https://github.com/diylxy/flutter_nuedc_v2下载apk安装体验。(到Release下载apk即可,文档仍在完善中)

安卓下的OpenCV虽然可以用,但它限制非常多,比如实时串流分辨率低,不支持numpy,对数据类型要求严格(这点在代码量大时优势明显,但在电赛只有四天三夜的场景下,会严重拖慢开发速度)……。在比赛时,还是建议大家采用Python实现视觉算法,Dart实现UI,通过lviop或者自己准备的开发框架通信。

九、注意事项

上一节提供了使用智能手机或任何带摄像头的安卓系统设备复刻题目全部功能的方法,如果希望1:1复刻出实物,这里提供主要元器件清单如下:

野火-鲁班猫3开发板

屏幕(需要自制转接板,PCB在开源工程里)

摄像头

三者通过USB和MIPI连接,将Python程序复制到文件系统,运行FlutterWrapper.py。随后在电脑上利用flutterpi_tool编译flutter工程,复制到文件系统后运行,前后端将自动建立连接。

十、测试结果

圆形(实际直径160mm),距离161cm处测试

等边三角形(实际边长139mm),距离161cm处测试

正方形(实际边长160mm),距离161cm处测试

多个正方形极限摆放测试(重叠正方形对数字无要求)

功耗在右下角方盒内显示,测量峰值功耗7W,空载功耗5W,满足题目10W以内的要求。

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
序列01.mp4
50
2
opencv.zip
72
3
C题_基于单目视觉的目标物测量装置.pdf
48
4
flutter_opencv1.zip
64
克隆工程
添加到专辑
0
0
分享
Logo GIF0
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

评论

全部评论(1
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航