ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

算盘视觉识别录入终端:基于树莓派与OpenCV的实现

算盘视觉识别录入终端:基于树莓派与OpenCV的实现 这个项目起源于一个很现实的痛点盘点货物、做账目核对时我习惯先用算盘快速累加数量手指拨珠的过程比在键盘上一个数字一个数字敲击要快得多也不容易打乱思路。但问题出在“数据落地”这一步——算盘算完了还得把结果抄进电脑抄录过程中经常出现“上下看错行、同级错一位”的情况返工比重新算一遍还费劲。所以我就琢磨能不能直接把算盘本身变成一台数据录入终端让算盘拨成什么样电脑就自动记录什么样中间不需要任何手写转抄。断断续续做了小半年最终的方案是用“普通算盘 俯拍摄像头 树莓派 OpenCV”组合成一套终端系统。摄像头从正上方盯住算盘视觉识别程序实时检测每一列珠子的位置把珠码翻译成十进制数字再通过串口或 USB 模拟键盘输出到电脑。这套东西做出来后实际测试的识别准确率在稳定光照下能到 99% 以上从拨珠到屏幕上出现数字的延迟大约 100 毫秒基本做到了“珠动数出”。这篇文章的主角是一个听起来很冷门、但做出来很有成就感的硬件软件混合项目。我这里把自己从头到尾的设计思路、硬件选型、识别算法、状态防抖、数据协议以及踩过的坑全部整理出来希望能给正在做类似物理计数转数字输入项目的朋友一点参考。1. 项目定位为什么要做一台“算盘录入终端”它到底解决什么问题1.1 算盘不是玩具而是高效的物理计数系统在开始之前我先解释一个可能被不少年轻开发者忽略的事实算盘是一套非常成熟的“物理状态机”。每一列珠子都代表一个十进制位珠子靠近横梁表示“被激活”远离横梁表示“不参与计数”通过约定上珠代表 5、下珠代表 1一根柱子就能表示 0 到 9 十个状态。这种设计的精妙之处在于它的状态是离散且无电源依赖的不拨它就一直保持原状。这恰恰是很多电子录入设备做不到的地方键盘敲完一行不保存页面刷新就丢算盘放在那儿三个月后再看一眼数字还在。如果我能在保留这种物理稳定性的基础上给算盘加一双“电子眼睛”那么它就成了一台低功耗、不弹窗、不会自动清空的数据输入设备。这个项目的本质不是去改造算盘的机械结构而是用视觉识别把“算盘珠子状态”转换为“数字化数据”。所以整个系统由三部分组成算盘本身作为输入介质俯拍摄像头作为感知器官树莓派上的 OpenCV 程序作为翻译大脑。1.2 数据录入终端的边界不是计算器也不只是摄像头读数做这个项目之前我最担心的是它变成一个“算盘拍照识别玩具”拍一张照片得出一个数字没有任何实用价值。所以我给自己定了一个边界它必须是一台能持续工作的终端而不是一次性识别工具。数据录入终端通常意味着三个能力。第一是持续监听算盘处于任何状态时系统都在运行等待新的拨珠动作。第二是事件触发只有当用户真正拨动珠子并形成一个新的稳定数字时系统才向上位机发送数据而不是每秒重复发送几十次没变化的内容。第三是可对接性系统输出的数据能直接被 Excel、数据库、扫码枪程序或者其他业务软件接收最好还能模拟成键盘输入让老旧的台账系统不改造也能用。按这个标准最合适的实现方式就变成了“视觉状态跟踪加事件上报”。摄像头以固定帧率采集图像算法实时识别每列珠子的位置维护一个当前数字状态当状态由旧值变为新值时触发一次数据发送。整个过程不需要物理按键确认也不需要额外点按钮用户的双手始终不用离开算盘。这才是这个项目最有价值的点让算盘变成一台“手指即输入”的外设。1.3 什么人适合参考这个项目我复盘整个项目后觉得最适合从这篇文章里获得价值的是三类人。一是做硬件项目但不想折腾复杂传感器的业余玩家摄像头方案比给每根柱子加霍尔传感器或磁簧开关简单太多且不用改造算盘本体二是做数字教学工具的教育从业者特别是教珠心算的老师可以用这套终端把学生的拨珠过程实时记录成数据流方便分析动作习惯三是在做“传统工具数字化”方向的开发者这个项目提供了一个不算复杂的样板如何把一套已有物理状态机用视觉方式桥接到现代软件生态。当然如果你只是想找一个“键盘替代品”那大可以直接买一个数字小键盘。但算盘录入终端的意义不在输入的绝对速度而在“先用手算再自动入账”的整个工作流体验。这一点在后面实测部分会详细展开。2. 算盘的数字规则与视觉检测区域建模2.1 先弄清楚珠码上珠一个代表 5下珠四个各代表 1算盘的样式很多我选用的是最普通的中国算盘横梁上方每列有 1 颗珠子横梁下方每列有 4 颗珠子。计数的规则是这样的当珠子被拨到靠近横梁的位置时它参与计数远离横梁的珠子不计数。上珠如果靠近横梁这一列的数字要加 5下珠中靠近横梁的珠子数量每颗代表 1。所以一列数字的计算公式是value 5 × 上珠激活数量 下珠激活数量由于一列只有一颗上珠和四颗下珠value 的取值范围自然就是 0 到 9。这个映射关系非常干净比用二进制码或者格雷码去理解算盘要直观得多。整把算盘有若干列从右往左依次是个位、十位、百位所以整把算盘当前表示的是一个多位十进制数。举个实际例子如果从右往左第三列也就是百位这一列上珠已经被拨到横梁附近下珠也有两颗靠近横梁那这一列的值就是 5 2 7。如果千位那列只有下珠靠近横梁三颗值为 3那么这两列合起来表示 3700 中的前两位。读算盘和读电子数字最大的不同在于算盘没有“清零”概念它每一列的值永远独立存在所以我后面做状态跟踪时也必须按列独立检测而不是把整把算盘当成一个孤立的大数字来处理。2.2 把视觉区域分成“列”和“梁”两类基准在做图像识别之前我首先在坐标系里把算盘的物理结构映射成一张二维区域图。横梁是一条横跨所有列的水平基准线在图像里我把它记作一条固定 y 坐标的参考线。每一根柱杆则是一条垂直基准线在图像里是一组固定 x 坐标的参考线。为什么要把这一层分清楚因为后续所有识别工作都可以归结为两个问题某个珠子在哪一列某个珠子相对横梁处于“激活”还是“非激活”状态。如果把这两个问题都提前固定在几何模型里那么视觉算法就不需要对每一列做独立的全图搜索大大简化了识别逻辑。在实际实现中我先用一块浅色底板固定算盘尽量让算盘边框在画面中处于水平位置然后用一个标定程序获取算盘左上角和右下角的坐标。通过角点检测得到四个边框点后对图像做透视变换让算盘区域变成一个规整的矩形确保横梁是一条近似水平的直线。2.3 检测区域划分的细节与容差标定完成后我会在代码里维护一个简单的数据结构列中心坐标数组 column_centers横梁的 y 坐标 beam_y。用户拨珠时珠子不一定完全水平所以每一列上下珠子的激活判定需要有一个容差范围。通常做法是设定一个阈值 beam_tolerance比如 12 到 15 像素只要珠子中心点与 beam_y 的纵向距离小于这个阈值就认为该珠子被拨到了横梁附近。列中心坐标也不是等间距的因为不同算盘的柱距可能略有差异。正确的做法是在标定阶段依次检测每一根柱杆的位置而不是从第一根柱到最后一根柱均匀切分。我是通过垂直方向投影来找柱杆位置的算盘柱杆在图像中会形成比较暗的细线投影后会出现明显的局部极小值把这些极小值提取出来就是每一根柱杆的 x 坐标。这套列坐标加横梁坐标的建模方式大概花了我一个下午的时间去调但一旦跑通后面所有算法都变得很顺。它相当于给识别程序画了一张“地图”每一个检测到的珠子都可以快速归位。3. 硬件布置与图像采集固定比识别更重要3.1 相机选择与安装位置很多人做视觉项目时最容易犯的一个错误是把识别算法的优先级放得过高却忽略了图像采集的稳定性。实际上在算盘录入终端这个项目里硬件安装的稳定性直接决定了识别率的上限。如果相机每次开机的位置都偏一点那么所有的透视变换和坐标标定都需要重新做一次这是最费时间的坑。我最终选用的是一款普通的 USB 摄像头分辨率 1280×720帧率 30 帧。把摄像头固定在算盘正上方约 35 厘米处镜头平面尽量与算盘盘面平行。这里有一个很容易被忽略的点镜头要尽可能对准算盘的正中心。如果镜头偏在某个角落透视畸变会让左右两侧的柱子间距在图像中表现不一致后续找柱杆位置时误差会明显增大。如果你手头有树莓派可以选择树莓派专用的 CSI 摄像头它的传输延迟比 USB 摄像头低而且不占用 USB 口。如果使用 CSI 摄像头建议选一块合适的排线长度保证相机支架在移动时不会扯到排线。我的第一版就是排线松动导致图像偶尔变绿排查了半天才发现是硬件接触问题。3.2 光照设计画质直接决定识别率算盘珠子的检测最容易受到光照影响。我一开始用自然光加一盏普通台灯台灯放在算盘侧面结果珠子在柱杆上形成了长长的阴影阴影区域被误判成深色轮廓导致识别率只有七成左右。后来我换成了 LED 面板灯从算盘正上方均匀打光同时用一张半透明的白色亚克力板当作匀光板挡在 LED 灯和算盘之间。这个改动之后珠子轮廓的稳定性提高了一截识别的抖动明显减少。从算法角度来说均匀光最大的好处是让珠子在 HSV 颜色空间中的 H 通道保持稳定这样我可以直接根据颜色阈值分割珠子而不需要每次都重新调整亮度参数。如果你的算盘是深色珠子建议不要直接走颜色分割而是用亮度阈值加轮廓识别如果可能的话我更推荐用浅色或彩色珠子分割起来省心很多。3.3 树莓派主控与供电接线主控我选择树莓派 Zero 2 W。这个选择一方面是因为它体积小、可以藏在算盘支架背面另一方面是它支持 USB OTG 模式后面可以把整个设备模拟成 USB 键盘直接插入电脑使用不需要额外安装上位机软件。供电方面树莓派 Zero 2 W 的稳定运行电流大约在 5V 1.2A 左右如果接入 USB 摄像头峰值电流会更高所以我用了一个 5V 3A 的电源适配器。摄像头如果使用 USB最好通过一个带屏蔽的 USB 线连接到树莓派的 OTG 口线材长度不要超过 50 厘米太长会有压降和信号衰减风险。整个硬件系统不需要额外搭建电路板因为摄像头和树莓派之间就是 USB 连接算盘本身完全是机械结构。也就是说整个终端只有三个可活动部件算盘、摄像头、树莓派。这一点让项目的硬件门槛几乎降到零只要你家里有一台电脑和一个算盘再花一两百块买一块树莓派 Zero 2 W 加摄像头就能复刻整套系统。3.4 组装顺序与固定方式我给算盘做了一个很简单的木质底座底座上开了一个略大于算盘框的凹槽算盘卡进去后不会有位移。底座上方立了两根铝型材支架摄像头通过一颗螺丝固定在支架顶部的横梁上。这样做的好处是可以随时微调摄像头高度和角度而不需要重新绑定算盘。组装顺序上我的习惯是先把算盘固定在底座上再把摄像头装到支架上然后接电开机最后运行一次标定脚本。千万不要先接好摄像头再去调整算盘位置因为一旦算盘发生位移之前标定的列坐标和横梁坐标全部作废而且这种误差不会自己修正。4. 核心识别算法珠子定位、聚类与激活判断4.1 颜色分割与轮廓提取识别流程的第一步是从图像中把珠子分割出来。我使用了 HSV 颜色空间因为 H 通道对环境亮度相对不敏感。假设我用的算盘珠是天蓝色那么设一组阈值例如 H 在 90 到 110S 在 80 到 255V 在 80 到 255这样就能把蓝色珠子从黄色的竹柱杆、深色横梁中分离出来。分割之后会产生不少噪点尤其是珠子的高光部分可能因为反光而在中间形成空洞。我用形态学“闭运算”处理用一个 5×5 的椭圆核对二值图做膨胀再腐蚀把珠子内部的空洞填上同时让轮廓变得更加完整。轮廓提取用的是 cv2.findContours然后通过轮廓面积筛选去掉面积过小或过大的连通域。珠子的实际面积在图像中约占 100 到 200 个像素所以我设置了一个面积范围。如果检测到的轮廓数量与算盘实际珠子数量不一致程序会输出一个 warning但不会崩溃而是等待下一帧继续识别。4.2 珠子坐标提取与聚类每个轮廓可以计算出一个最小外接圆圆心坐标就是这颗珠子在图像中的中心位置。由于算盘上珠和下珠的珠子大小并不完全相同但差别不大我直接用圆心位置代表珠子的空间坐标。接下来是关键的一步把所有检测到的珠子中心坐标按照列坐标 column_centers 进行聚类。最简单的做法是使用最近邻原则对于每个珠子中心点计算它与所有 column_centers 的距离把它归到距离最近的那一列。这里要注意一个问题当珠子位于两个相邻柱子之间时会出现归属模糊的情况。我的处理方式是设置一个最大距离阈值如果珠子中心到最近列的距离超过了这个阈值就认为它是悬空状态不属于任何一列暂时忽略。聚类完成后每一列得到若干珠子中心的 y 坐标。接下来根据 y 坐标与横梁参考线 beam_y 的关系把珠子分为“上珠区”和“下珠区”。由于算盘横梁很细在图像中通常只占 2 到 4 个像素所以划分规则很简单y 坐标小于 beam_y - beam_tolerance 的珠子属于上方y 坐标大于 beam_y beam_tolerance 的珠子属于下方。落在容差范围内的珠子就是已经被拨到横梁附近的激活珠子。4.3 激活状态与列数字的映射激活状态判断是整个算法里最容易产生误解的地方。这里的“激活”指的是珠子被拨到了靠近横梁的位置而不是指珠子在画面中可见。也就是说算盘上所有珠子在画面里一直是可见的但只有靠近横梁的那部分才参与计数。判断逻辑是对于一列的下珠区统计所有 y 坐标与 beam_y 距离小于 beam_tolerance 的珠子数量记为 lower_active。对于上珠区同样统计记为 upper_active但这个数量只可能有 0 或 1。因此该列的数字就是value 5 × upper_active lower_active如果识别结果出现 lower_active 大于 4 或者 upper_active 大于 1 的情况就说明这一帧的图像识别有误我会标记该列为 invalid并在状态机中拒绝更新上一层状态。4.4 同一柱杆上两颗珠子粘连的处理实际使用中下珠区的四颗珠子在拨动时可能挤在一起导致轮廓提取时把两颗珠子合并成一个大的连通域。这种现象在视觉上表现为轮廓的宽高比明显异常面积也接近正常珠子的两倍。我处理这个问题的方法是在轮廓检测后额外判断每个轮廓的等效直径。如果某个轮廓的等效直径超过了单颗珠子直径的 1.6 倍我就把它当作两个重叠珠子来拆分具体做法是在该轮廓中心做一次垂直方向的二次分割把连通域一分为二分别计算两个子区域的中心点。这个方法在稳定光照下效果很好但在极端光照条件下偶尔会失效所以我同时保留了“有效性校验”机制一旦识别出列数字不合理就保持上一个有效状态不把错误数据发出去。5. 状态跟踪与数据输出防抖、帧数据与自动录入5.1 为什么需要状态跟踪而不是每帧都发数据如果你直接运行识别程序并且实时打印每一帧的数字结果会发现一个现象即使珠子完全静止识别出的数字也会在相邻帧之间出现微小抖动。这个抖动的来源不是算盘变了而是图像噪声、珠子表面反光、环境光微变等因素让轮廓边缘产生了一两个像素的移动从而让激活判定的容差范围内偶尔多进一颗珠子。如果把这些抖动直接上传给电脑那么终端的数据流就会像一卡一卡的乱码Excel 里会连续冒出一堆错误数字。所以我在程序里维护了一个状态机当前有效数字 current_value只有检测到连续多帧的数字都相同且与当前值不同才把新值作为一次稳定的拨珠结果提交。5.2 防抖参数设置与事件触发逻辑我采用的防抖策略是“连续 N 帧一致”模式。N 从 3 到 5 都可以这个数值取决于摄像头帧率。在 30 帧下3 帧意味着 100 毫秒的确认时间对人工拨珠速度来说已经足够灵敏同时又不会误触发快速抬手造成的短暂遮挡。具体逻辑如下程序维护一个 last_value 数组每次新帧计算出 value 后把它放入数组末尾同时检测数组中最近 N 帧的值是否全部相同。如果相同且与 current_value 不同就触发一次提交current_value 更新为新值。如果在 N 帧之内出现了不同的值则说明用户还在拨珠过程中数组清空重新累计不触发提交。这个机制还有一个好处它能天然过滤掉手在拨珠瞬间遮挡一部分珠子的情况。比如手移开时偶然把某个下珠拨动了 1 毫米还没到横梁位置下一帧该珠子又回到了原来的位置由于没有连续 N 帧形成稳定状态这次扰动根本不会进入上报流程。5.3 数据帧格式与串口输出当新的稳定状态确认后程序需要把这个状态发送给上位机。我设计了一个很轻量的 ASCII 帧格式既方便调试也不依赖特定库。每一帧由一行文本组成内容包含帧头、列数、各列数值和一个简单校验ABC|10|5|2|3|7|0|0|0|0|0|0|5901ABC 是固定帧头用来做数据同步第一个数字是列数后面的数字分别对应从右往左每一列的数值最后的 5901 是前面所有字符的简单累加校验和对 10000 取模的结果。上位机收到这行数据后按竖线分拆校验帧头和校验和正确后即可使用。整个帧长度很短串口波特率设为 115200 时一帧的传输时间不到 1 毫秒不会成为性能瓶颈。5.4 把树莓派模拟成 USB 键盘免上位机方案在项目做到中后期的时候我发现很多场景下用户根本不想额外安装一个接收程序而是希望把算盘终端当成一个即插即用的输入设备。这时候树莓派 Zero 2 W 的 USB OTG 功能就派上用场了。我可以把树莓派配置成 USB HID 设备也就是让电脑认为它是一把键盘。当算盘状态稳定变化后程序不只是通过串口发送文本帧同时还能模拟键盘输出一串数字字符。这个方案的流程是识别到算盘每列数字变化程序把整列数字拼成一个多位十进制数通过 USB HID 协议模拟键盘敲击数字键如果算盘上所有列都被清成 0可以模拟按下回车键表示一次录入结束。实际使用时光标停留在 Excel 任意单元格中我拨动算盘珠子数字就会自动敲进去确认无误后把珠子清空系统自动回车换行光标自动跳到下一个单元格。整个流程下我真的只需要手拨珠子不需要碰键盘。我在树莓派上启用这个功能的常用方法是使用 ConfigFS 配置 USB Gadget把树莓派模拟为 HID 键盘。这一步需要一点 Linux 内核配置知识但在树莓派官方系统上只需要打开对应的 overlay 并编写一个简单的 Gadget 配置脚本即可。如果你不想折腾也可以直接跑一个 Python 脚本使用 usb_hid_tools 库来做 HID 模拟。需要注意的是模拟键盘输入的实现位置应该在“状态确认”之后而不是在每一帧识别结果之后否则键盘会重复输出相同的数字。我在这里加了一个标志位 last_sent_value只有新值与上次发送值不同时才执行键盘模拟。6. 实测中踩过的坑光照、透视、串口干扰和校准方式6.1 光照变化的坑同一副图像上午能用下午失灵这个问题在项目测试中出现过不止一次。上午十点自然光从窗户照进来画面还很均匀到了下午三点太阳角度变了算盘边框的影子直接横在珠子上颜色分割后的二值图像突然多了一大块噪声。我一度以为是算法不够健壮后来发现问题的根源是“背景亮度变化过快”。最直接的解决办法不是调算法而是从物理上消除环境光的影响。我把整个算盘和摄像头支架放进一个半透明的亚克力箱体里箱体内侧贴了一张 LED 面板灯让算盘处于一个独立、稳定的光照环境中。从那之后同一组 HSV 阈值和亮度参数在一天内的任何时间都能稳定工作。在软件层面我也做了一个小的自适应处理每 100 帧重新计算一次图像的背景亮度中位数如果发现整体亮度过高或过低就自动调整 V 通道的上下界。这个调整不是实时做的而是每隔一段时间做一次慢速更新避免因手部阴影造成亮度突变而触发阈值抖动。6.2 透视变形的坑看似平行实际歪了摄像头从正上方拍摄时如果镜头光轴没有完全垂直于盘面算盘的边框就会在图像里呈现梯形横梁也不再是一条水平线而是一条斜线。用这样的图像直接跑列坐标和横梁坐标误差会随着列数增加而累积最右侧的柱子可能偏离 20 到 30 个像素。解决方法是加一次透视校正。我在算盘底座的四个角贴了四个黑色圆形标记标定程序先检测这四个标记的圆心坐标然后通过 cv2.getPerspectiveTransform 把图像变换成一个标准矩形。校正后横梁变成水平线列中心坐标间距也变成均匀的。这个校正只需要在算盘被固定住后做一次之后每次开机可以自动加载保存好的变换矩阵。这里有个细节透视校正之后图像分辨率可能会变化原本 1280×720 的图像会被裁剪或者拉伸。我是在校正后的图像上重新执行列坐标和横梁坐标检测的所以标定顺序必须是“先校正再找柱杆位置”不能反过来。6.3 串口干扰和数据丢失的坑用 USB 转串口调试时我遇到过偶尔丢帧的情况尤其是在树莓派同时运行摄像头采集和串口输出时CPU 占用率一高串口缓冲区就可能溢出导致上位机收到残缺的行。解决的办法是给串口写入加上锁机制并且把数据封装成完整的一行一次性写入。Python 的 serial 库写入速度很快但为了避免多个线程同时写串口我在树莓派程序里用了一个简单的 threading.Lock。同时在接收端上位机必须按换行符来切割数据帧并在校验和不匹配时丢弃当前帧而不是把残缺帧当成有效数据。实践下来只要完整帧格式和校验和做对即使在 CPU 占用较高的情况下丢帧率也基本可以忽略。6.4 校准步骤我从手动标定到半自动标定的过程第一版校准脚本要求用户在图片上手动点击横梁左右两端和每一根柱杆的位置这很耗时而且每次重新固定算盘都要做一遍。后来我把它改成了半自动流程程序自动检测底座四个角点做透视校正在校正后的图像上对整行像素做垂直投影找出柱杆位置程序在柱杆位置附近寻找横梁的上下边缘拟合出横梁中心线用户只需要确认一次结果如果有一两列柱杆位置偏移手动微调即可。这个半自动流程把标定时间从 3 分钟缩短到了 30 秒以内。更重要的是每次固定算盘后重新执行一遍标定能保证整个坐标系始终与当前安装状态保持一致。6.5 珠子的材质也会影响识别我第一把算盘的珠子是深红色木质漆面反光度很高高光在图像中形成亮斑导致分割后的二值图里珠子中心出现一个“黑洞”让轮廓面积变小。后来我直接用天蓝色的塑料珠子替换了原来的珠子颜色分割效果一下子好了很多。如果你不想换珠子也可以在分割时使用 HSV 中的 S 通道加 V 通道的组合逻辑把高光区域填掉但总体处理起来会繁琐一些。7. 复盘性能数据、局限与三种可落地改进方向7.1 最终实测性能指标在所有代码和硬件调整完成后我做了一组简单的实验来评估终端性能。固定算盘位置摄像头 30 帧采集树莓派 Zero 2 W 上运行 Python 3.9 加 OpenCV最终得到的指标如下单帧识别耗时平均约 45 毫秒连续 3 帧防抖后的事件触发延迟约 150 毫秒正确识别率在稳定光照和固定机位下测试 200 次拨珠中只有 2 次出现无效状态被拒绝0 次错误数字被输出自动键盘输入延迟从拨完珠子到文字出现在 Excel 单元格里大约 200 毫秒体感很顺。这套硬件配置的缺点是树莓派 Zero 2 W 的内存只有 512 MB运行 OpenCV 时偶尔内存占用偏高所以在程序中我关闭了所有不必要的窗口显示只保留命令行日志和帧处理函数实测没有出现卡死或内存飙涨的问题。7.2 这个方案能做什么不能做什么它能很好地完成“周期性数字录入”这个场景比如盘点、计数、课堂珠算记录。它也能让算盘变成一台独立的 USB 输入设备接上电脑就能用无需额外软件。它不能做的也很明确如果你需要高速连续录入大量动态变化的数字比如每秒钟拨动十几下柱子那么 150 毫秒的防抖延迟会产生明显的滞后感如果算盘的柱距特别窄柱杆之间的边缘在图像中模糊不清列坐标标定也可能出错。另外这个方案对背景和光照有硬性要求完全不遮光的环境下想靠算法硬扛反光体验不会太好。7.3 三种可落地的后续改进方向第一个方向是改造成“无摄像头”的纯物理传感器方案。在每根柱杆上安装小型磁性霍尔传感器把珠子替换成含磁铁的定制珠这样就不需要视觉识别了响应速度和稳定性都会提升但制作成本会翻倍而且算盘的手感可能需要重新适配。第二个方向是把识别算法迁移到边缘 AI 设备上比如在树莓派上加载一个轻量级的目标检测模型直接识别不同的珠子状态。这个方案能提升对复杂背景和光照变化的鲁棒性但也需要更多算力小内存开发板跑起来比较吃力。我个人的建议是先把手动规则算法优化到极限再考虑是否需要上模型。第三个方向是增加“操作日志”功能让终端不是只在稳定状态发生变化后输出一个数字而是记录每一次拨珠的原始轨迹包括哪一列珠子在什么时间发生了位移、位移方向是靠近还是远离横梁。这个数据对珠心算教学有独特价值能帮助老师分析学生拨珠时的手指习惯、停顿位置、错误修正过程已经超出了单纯数据录入的范畴。这个项目到此为止最让我满意的部分是它完成了一件事情把一件传统的机械工具用最简单可行的视觉方案接进了现代办公流程。它没有高大上的传感器没有复杂的神经网络也没有昂贵的机械臂用的只是一个摄像头、一块树莓派、一把普通算盘和几百行 Python 代码。如果你也想做一个类似的“传统工具数字化”项目我建议不要一开始就想着把所有功能做全先把“固定好、识别准、防抖稳、输出通”这四个环节跑通再考虑要不要加花哨的东西。最后再分享一个细节在整个项目里真正花掉我最多时间的不是 OpenCV 的算法也不是树莓派的配置而是给算盘做一个能稳到“纹丝不动”的底座。算盘底座稍微晃动一点所有标定位置就白费了。所以如果你打算复刻这个项目请一定多花点心思在机械固定上它能帮你省下后面至少一半的调试时间。
返回列表