四足机器人视觉循线:从阈值分割到HSV跟踪的嵌入式实现

发布时间:2026/5/24 3:02:40

四足机器人视觉循线:从阈值分割到HSV跟踪的嵌入式实现 1. 项目概述当四足机器人“看见”线条在机器人领域让一个机械装置自主地跟随一条画在地上的线听起来像是一个经典的入门项目。但当你把这个任务交给一个四条腿、像小动物一样行走的机器人并且让它仅凭一个摄像头来“看”路时整个挑战的维度就完全不一样了。这不再是简单的传感器逻辑判断而是一次对“感知-决策-行动”完整闭环的实战演练。我最近就完成了这样一个项目为一个自制的四足机器人平台嵌入一套计算机视觉系统让它能像真正拥有视觉一样追踪并跟随一条彩色路径。这个项目的核心价值远不止于让机器人走个直线或拐个弯。它本质上是在探索如何将复杂的图像信息在资源有限的嵌入式环境中转化为稳定、实时的控制指令。我们抛弃了依赖强大上位机进行图像处理的传统思路转而追求一种高度集成、低成本的嵌入式解决方案。这意味着所有的“看见”、“思考”和“行动”都发生在机器人本体这个小小的“大脑”和“眼睛”里。为了实现这个目标我对比并实践了两种主流的技术路径一种是基于传统图像处理中的阈值分割方法利用Android手机作为摄像头和初级处理器通过Processing语言进行逻辑判断另一种则是采用专用的Pixy智能视觉传感器直接在HSV颜色空间进行颜色跟踪由Arduino负责最终的运动控制。两种方案各有优劣贯穿了从算法原理到工程落地的完整思考。通过这个项目你不仅能了解到计算机视觉在机器人控制中的实际应用更能深刻体会到在约束条件下成本、算力、实时性进行技术选型和系统集成的工程艺术。无论你是机器人爱好者、嵌入式开发者还是对机器视觉感兴趣的学生相信这篇详实的记录都能给你带来直接的参考和启发。2. 项目整体设计与核心思路拆解2.1 核心需求与约束条件分析在动手之前明确项目的边界和目标是成功的关键。这个四足循线机器人的核心需求非常清晰让机器人仅依靠视觉传感器自主、稳定地跟随一条预设的地面路径。然而“仅依靠视觉”和“四足平台”这两个前提带来了几个必须面对的硬性约束实时性要求高四足机器人的步态运动是时序精密的任何一个决策延迟都可能导致失步或摔倒。图像处理速度必须跟上机器人的运动节奏通常要求处理帧率在10Hz以上。嵌入式算力有限我们无法在机器人身上搭载一台高性能计算机。主控单元如Arduino的计算能力和内存都非常有限复杂的图像算法必须经过精简或由专用硬件加速。环境光干扰室内光线可能不均匀或有自然光变化。视觉算法必须具备一定的光照鲁棒性不能因为阴影或光线强弱变化就“失明”。平台动态稳定性与轮式机器人不同四足机器人在运动时摄像头视角会有规律性的晃动和倾斜。图像处理算法需要在一定程度上容忍这种由自身运动带来的图像抖动。成本与复现性作为一个开源分享项目我们希望它使用的部件易于获取、价格低廉且搭建过程清晰便于其他人学习和复现。基于这些约束项目的整体设计思路可以概括为选择一个合适的视觉感知方案将图像信息简化为一个关键的导航参数通常是路径中心线的横向位置然后将这个参数映射到四足机器人的步态控制逻辑中形成闭环。2.2 技术方案选型两条路径的权衡面对核心需求我规划并实践了两条技术路径它们代表了嵌入式视觉中两种不同的设计哲学。方案一基于移动设备与通用算法的分离式处理这个方案的核心是利用现有消费级硬件的强大性能。我选用了一部旧安卓手机作为“机器人的眼睛和初级大脑”。手机摄像头负责采集图像并通过自行编写的Processing程序运行在手机上进行图像处理。处理结果如“向左转”或“向右转”的指令通过蓝牙发送给机器人的“小脑”——Arduino控制器由它来驱动舵机执行步态。优势充分利用了手机强大的计算能力和高清摄像头可以运行相对复杂的图像算法如Otsu阈值法。开发环境Processing对初学者友好调试和算法迭代非常方便可以直接在手机屏幕上看到处理效果。挑战系统复杂度高涉及Android、Processing、蓝牙通信、Arduino多个模块的联调。功耗较大需要为手机单独供电。整体系统的体积和重量也更大。方案二基于专用视觉传感器的嵌入式集成方案这个方案追求极致的集成和效率。我选用了PixyCMUcam5这款开源智能摄像头。它内部集成了专用的图像处理芯片能够直接在传感器端完成颜色识别和目标跟踪然后通过简单的通信接口如SPI、I2C只把结果数据如目标物体的坐标、大小输出给主控器Arduino。优势极大地减轻了主控器的计算负担。Arduino只需要解析几个字节的数据就能做出决策。Pixy针对颜色跟踪进行了硬件和算法优化处理速度快50Hz且对光照变化不敏感使用HSV色彩空间。系统集成度极高接线简单体积小巧。挑战Pixy的功能相对固定主要是颜色块跟踪算法定制空间小。初次投入成本比用旧手机高。需要学习其特定的配置和数据通信协议。实操心得方案选择背后的逻辑对于教学、演示或快速验证算法原型方案一更具优势因为你可以在电脑上快速修改Processing代码实时看到阈值分割的效果学习图像处理的原理。但对于追求稳定性、响应速度和真正“嵌入式”感觉的最终产品方案二无疑是更专业的选择。Pixy将复杂的视觉问题封装成了一个“黑盒”传感器让开发者可以像使用超声波测距模块一样使用视觉功能这是工程上的巨大进步。在本项目中我首先用方案一打通了所有流程并验证了可行性最终采用方案二实现了更稳定可靠的运行。2.3 机器人平台设计与搭建要点机器人本体是算法的承载平台。我们基于开源设计使用3mm厚的铝板切割出机身和腿部的结构件通过8个舵机HK15138型号实现四条腿的12个自由度运动每条腿的髋关节和膝关节。每个舵机都由Arduino的PWM引脚独立控制。动力与供电整个系统由一块12V的锂聚合物电池供电。由于舵机工作电压通常为6V左右我们使用了一个分电板它既能将电池电压分配给各个部件也集成了一个降压模块为舵机组提供稳定的6V电源。这里有个关键细节务必确保你的降压模块能提供足够的持续电流所有舵机同时运动时的峰值电流可能高达数安培否则会导致舵机无力或控制器重启。步态设计四足行走的核心是保持静态或动态平衡。我们采用了简单但有效的“对角线步态”。想象一下动物小跑左前腿和右后腿同时抬起、迈出、放下然后是右前腿和左后腿。这样总能保证有三个或两个对角支撑点在地面上防止机器人倾覆。在代码中我们通过精心编排8个舵机的动作顺序和延时来实现这种步态。前进同步控制位于机器人左侧坐标系I、II象限的“肩部”舵机以及位于对角线位置I、III象限和II、IV象限的“肘部”舵机。转向通过让身体一侧的腿步幅缩小另一侧步幅放大或原地踏步来实现原地转弯。摄像头安装摄像头的视角和高度至关重要。我们将其安装在机器人头部略微前倾俯视地面。视角需要覆盖机器人前方足够远的距离让机器人有反应时间但又不能太远导致路径在图像中过于细小。经过测试摄像头光轴与地面夹角大约在30-45度之间比较合适。安装务必牢固减少行走带来的振动模糊。3. 核心细节解析两种视觉算法的原理与实现3.1 方法一阈值分割——从图像中“剥离”出路径当路径是简单的黑线背景是白纸时最直观的想法就是把图像变成非黑即白的二值图黑的地方就是线白的地方就是背景。这个过程就是阈值分割。关键在于如何选择那个“阈值”。3.1.1 Otsu大津算法让数据自己说话Otsu法是一种自动确定全局阈值的经典算法。它的核心思想非常巧妙找到一个阈值使得分割后的前景黑线和背景白纸两类像素的类间方差最大化。通俗地说就是让“线”里面的像素灰度值尽可能相似都暗“背景”里的像素灰度值也尽可能相似都亮并且“线”和“背景”之间的灰度差异尽可能大。算法步骤简述将彩色图像转换为灰度图。计算灰度图像的直方图统计每个灰度级有多少个像素。遍历所有可能的灰度级0-255将每个灰度级k作为候选阈值将像素分为两类C0灰度k和C1灰度k。对于每个k计算两类像素占整图的比例权重、平均灰度进而计算类间方差。选择使类间方差最大的那个k即为最佳阈值。在Processing中实现Otsu算法后我们得到了干净的二值图像。但它的缺点也很明显计算量大。每一帧都需要计算直方图和遍历所有灰度级在手机处理器上虽然能跑但会限制整体帧率。而且它依赖于灰度信息如果背景不是均匀的白色或者光照导致“白纸”看起来是灰色效果就会变差。3.1.2 实验性RGB阈值法一种轻量级的替代方案既然我们的场景非常特定黑线白底有没有更简单快速的方法当然有。我们直接分析黑色和白色在RGB颜色空间中的数值特征。我采集了在不同光照条件下模拟环境光变化的200个“黑点”和“白点”的RGB值。通过观察和实验我发现了一个稳定的规律对于白点它的R、G、B三个通道的值都很高且接近对于黑点三个值都很低。但简单判断RGB的总和是否小于某个值如250并不完全可靠因为某些阴影下的“白点”总和也可能偏低。经过反复试验我找到了一个更鲁棒的组合判断条件// 判断一个像素是否为“黑线”上的点 boolean isBlack(int r, int g, int b) { if ((r g b) 250) { // 总亮度很低 if ((g - b) 30) { // 绿色不比蓝色亮太多避免深蓝色误判 if ((r - b) -30) { // 红色不比蓝色暗太多避免深紫色误判 return true; } } } return false; }这个经验性的阈值组合在测试中对黑点的识别成功率达到了97%。它的优势在于速度极快每个像素只需要进行几次整数比较避免了Otsu法中的浮点运算和迭代显著提升了处理速度为实时控制赢得了宝贵时间。注意事项阈值法的局限性无论是Otsu法还是实验阈值法都属于基于颜色的静态分割。它们共同的问题是严重依赖预设的颜色特征。一旦环境光颜色发生变化比如在暖色灯光下白纸偏黄或者路径与背景的颜色对比度不够算法就会失效。因此这类方法更适合受控的、环境固定的室内场景。3.2 方法二HSV颜色空间跟踪——专注色彩本质为了获得更好的环境光鲁棒性我们转向HSV颜色空间并采用专用硬件Pixy来实现。HSV将颜色表示为Hue色调表示是什么颜色红、黄、绿...这是我们识别路径的关键。Saturation饱和度表示颜色的纯度。Value明度表示颜色的亮度。Pixy的聪明之处在于它主要利用H和S两个通道来识别颜色而忽略了V明度。这意味着无论光线强弱只要还能看清颜色只要路径的色调和饱和度在一定范围内Pixy就能把它找出来。这大大提升了系统在不同光照条件下的稳定性。3.2.1 Pixy的工作原理硬件加速的视觉流水线Pixy不仅仅是一个摄像头它内部包含一个图像传感器和一个专用的微处理器。这个微处理器在图像数据生成的过程中就同步进行处理这种“流水线”式的工作方式效率极高。颜色学习用户通过Pixy官方软件或按下其按钮将摄像头对准目标颜色。Pixy会记录下该颜色区域像素的H和S值范围形成一个“颜色签名”。快速扫描与聚类Pixy逐行扫描图像对每个像素判断其H和S值是否落在已学习的“颜色签名”阈值范围内。如果是则将其标记为前景像素。生成包围盒Pixy会将连续的前景像素聚类并为其生成一个最小的矩形包围盒。同时它会计算并输出这个包围盒的中心坐标(x, y)、宽度、高度以及对应的颜色签名编号。数据输出Pixy通过SPI接口只将这些结构化的数据几个整数发送给Arduino而不是原始的图像数据流。这减少了超过99%的数据传输量。3.2.2 在Arduino中解析Pixy数据Arduino端的工作变得异常简单。我们使用Pixy2库核心代码逻辑如下#include Pixy2.h Pixy2 pixy; void setup() { Serial.begin(115200); pixy.init(); pixy.setLamp(1, 1); // 打开灯光辅助照明可选 pixy.setLED(255, 255, 255); // 设置指示灯颜色 } void loop() { static int last_x 0; // 记录上一次的x坐标 pixy.ccc.getBlocks(); // 获取识别到的色块信息 if (pixy.ccc.numBlocks) { // 如果识别到至少一个色块 int x_center pixy.ccc.blocks[0].m_x; // 取最大的色块索引0的中心x坐标 // 根据x_center的位置决定机器人行动 if (x_center 130) { turnLeft(); } else if (x_center 170) { turnRight(); } else { moveForward(); } last_x x_center; } else { // 没看到线可以执行停止或沿上次方向小步探索 stopOrSearch(last_x); } delay(100); // 控制循环频率与机器人步态周期匹配 }通过对比Pixy输出的x坐标与图像中心区域的边界如130和170我们就能判断路径是偏左、偏右还是居中从而发出相应的转向或前进指令。4. 系统集成与机器人运动控制实现4.1 运动控制逻辑从视觉坐标到舵机角度视觉系统告诉我们“线在哪里”运动控制系统则需要翻译成“腿该怎么动”。我们定义了一个简单的反应式控制策略决策输入路径中心在图像中的x坐标x_center。Pixy的图像x轴范围是0到399中心点是199.5。决策规则如果x_center 130则认为路径偏左机器人需要左转。如果130 x_center 170则认为路径基本居中机器人直行。如果x_center 170则认为路径偏右机器人需要右转。为什么是130和170这两个阈值定义了图像中心的一个“死区”。因为摄像头图像和机器人运动都存在微小抖动设置一个中间区域可以避免机器人在路径中心附近频繁左右摇摆使运动更加平滑。这个值需要通过实际测试微调。4.2 四足步态的程序化实现控制8个舵机协调运动是代码中最繁琐的部分。我们需要为每个舵机定义其在“前进”、“左转”、“右转”、“停止”等动作中的目标角度和运动时序。以“前进”步态的一个周期为例代码框架如下// 假设servo[0]-[3]为左前、右前、左后、右后的“肩部”舵机控制腿前后摆动 // servo[4]-[7]为对应的“肘部”舵机控制腿抬起放下 // 所有舵机初始角度为90度中间位置 void moveForwardStep() { // 阶段1抬起左前腿I和右后腿IV servo[4].write(70); // 左前肘部收缩抬腿 servo[7].write(110); // 右后肘部收缩抬腿 (注意安装方向可能导致角度增减相反) delay(100); // 抬腿时间 // 阶段2抬起的腿向前迈身体重心前移 servo[0].write(80); // 左前肩部向前摆 servo[3].write(100); // 右后肩部向前摆 // 同时支撑腿右前、左后的肩部轻微后摆以推动身体 servo[1].write(100); servo[2].write(80); delay(200); // 迈步时间 // 阶段3放下载腿 servo[4].write(90); // 左前肘部复位 servo[7].write(90); // 右后肘部复位 delay(100); // 落地稳定时间 // 阶段4抬起右前腿II和左后腿III重复上述过程形成交替步态 // ... 类似代码操作servo[5], servo[6], servo[1], servo[2] }关键参数调试舵机角度10-15度的步进角度是一个经验值。角度太大会导致步幅过大机器人晃动剧烈摄像头图像抖动厉害角度太小则移动速度太慢。需要在实际地面上测试调整。动作延时delay()的时间决定了机器人运动的速度和流畅度。抬腿、迈步、落地的每个阶段都需要给予舵机足够的时间到达指定位置。整个步态周期约400-600ms这决定了机器人的最大行动频率。4.3 视觉-运动闭环的时序同步这是整个系统稳定性的关键。Pixy的帧率高达50Hz每20ms一帧但机器人完成一个步态周期需要几百毫秒。我们不能让视觉决策快于机械执行否则会产生指令堆积和混乱。采用的同步策略是读取视觉数据从Pixy获取当前路径中心的x坐标。做出决策根据x坐标判断下一步动作直行、左转、右转。执行一个步态周期调用对应的moveForwardStep(),turnLeftStep()或turnRightStep()函数这些函数内部包含了完整的、耗时几百毫秒的舵机动作序列和延时。等待动作完成在步态函数执行期间不进行新的视觉数据读取和决策。循环一个步态周期结束后返回步骤1读取新的视觉数据开始下一个循环。这种“感知-决策-执行-等待”的循环确保了机器人的动作总是基于最新的视觉信息并且有足够的时间完成物理动作避免了系统因处理过快而失控。5. 常见问题、调试技巧与优化实录在项目开发过程中我遇到了无数坑也积累了许多宝贵的调试经验。这里分享几个最具代表性的问题和解决方法。5.1 视觉系统常见问题排查问题1Pixy识别不到颜色或识别不稳定。可能原因及排查光照问题环境光太暗或存在强烈反光。解决确保光照均匀必要时打开Pixy自带的LED补光灯pixy.setLamp(1,1)。避免阳光直射或点光源造成的高光。颜色学习不准确学习样本时摄像头距离、角度与运行时不一致或者样本区域包含了其他颜色。解决重新学习颜色确保学习时摄像头正对目标颜色区域且该区域充满视野中心。可以学习多个样本以提高鲁棒性。阈值过窄Pixy默认的色相Hue阈值可能较窄。解决使用PixyMon软件连接摄像头查看识别到的色块和其参数适当调宽色调和饱和度的阈值范围。颜色本身不易识别如黑色、白色、灰色在HSV空间中饱和度很低难以与背景区分。解决更换路径颜色优先选择红色、蓝色、绿色等高饱和度的颜色。问题2阈值分割法手机方案在光线变化时失效。可能原因固定的RGB阈值无法适应亮度的整体变化。解决思路动态阈值可以尝试计算图像的平均亮度然后根据平均亮度动态调整黑白判断的阈值。例如整体偏暗时降低判断为“黑”的(RGB)阈值。切换色彩空间在Processing中实现将RGB转换为HSV然后像Pixy一样主要依据H和S通道进行阈值分割能显著提升鲁棒性。图像预处理对图像进行高斯模糊可以平滑掉一些小噪声点使用形态学操作如开运算、闭运算可以消除二值图像中的小孔洞和孤立白点让线条更连续。5.2 机器人运动系统常见问题排查问题3机器人行走时抖动严重或容易摔倒。可能原因及排查机械结构松动检查所有螺丝和舵机臂是否紧固。四足机器人对结构刚性要求很高。舵机扭矩不足HK15138舵机扭矩约为1.5kg·cm对于这个尺寸的铝板机器人可能处于临界状态。解决尝试减轻腿部末端的重量或者换用扭矩更大的舵机如MG995。步态时序不当抬腿、迈步、放下的时间分配不合理。解决仔细调整每个delay()的时间。特别是“抬腿”和“放下”阶段时间太短会导致舵机未到位就执行下一步产生抖动时间太长则影响行走速度。可以尝试在舵机动作指令后增加一小段延时等待舵机稳定。重心过高摄像头和电池等较重部件安装位置太高。解决尽可能将重物降低到机身下部。问题4机器人无法准确转向总是转过头或转不够。可能原因转向步态的角度差设置不当或者视觉决策的“死区”和转向灵敏度不匹配。调试方法分离测试先屏蔽视觉部分编写测试代码让机器人固定执行“左转5步”或“右转3步”观察其实际转弯角度。调整转向步态中舵机的角度差直到获得满意的单步转弯角度。调整视觉死区修改代码中的转向阈值如130和170。如果机器人总是轻微“画龙”可以适当增大中心死区如120到180。如果机器人对路径偏移反应迟钝转弯不及时则缩小死区。引入比例控制更高级的做法是根据x_center偏离图像中心的距离来动态调整转向的幅度。例如偏离越多转向步态中舵机的角度差就设置得越大实现“小偏微调大偏急转”的平滑控制。5.3 系统集成与性能优化建议1. 电源噪声滤波舵机在启动和制动时会产生很大的电流尖峰可能引起电源电压波动导致Arduino或Pixy意外复位。解决在Arduino的电源入口处并联一个100-470uF的电解电容用于缓冲大电流需求。每个舵机的电源线附近并联一个0.1uF的陶瓷电容用于滤除高频噪声。2. 通信稳定性如果使用蓝牙手机方案确保波特率设置正确并处理通信中断的情况。在代码中加入超时判断和重连机制。对于Pixy的SPI通信确保接线牢固时钟频率在Arduino和Pixy都能接受的范围内。3. 代码结构优化避免在loop()函数中使用长时间的delay()这会阻塞所有其他操作。可以考虑使用状态机和非阻塞定时millis()来管理步态周期和视觉采样周期让系统更高效、响应更及时。4. 增加故障恢复在代码中增加状态监控。例如如果连续多次从Pixy读取不到数据或读取的数据明显异常如坐标超出范围则让机器人进入停止状态并闪烁LED报警而不是基于错误数据乱走。通过这个项目我深刻体会到嵌入式视觉机器人是一个典型的跨学科系统集成挑战。它要求开发者不仅理解算法原理还要对硬件特性、机械结构、实时控制有全面的把握。每一个环节的微小偏差都可能被放大为整个系统的失败。然而当看到这个自己亲手打造的小机器颤颤巍巍却又坚定不移地沿着那条彩线前进时所有的调试和折腾都变得无比值得。这或许就是机器人开发的魅力所在——在物理世界中让代码和逻辑真正地“行走”起来。

相关新闻