【工程训练/水中机器人】水下管道智能巡检【视觉部分】总结
【工程训练/水中机器人】水下管道智能巡检【视觉部分】总结本文为第七届大学生工程训练综合能力竞赛中【水下管道智能巡检赛项】和第十四届国际水中机器人大赛【水下管道智能巡检组】视觉部分总结。
前言我在队伍中主要负责机器人视觉功能的实现,所以在本篇参赛总结中只会涉及视觉功能实现的思路和过程。
提示:下文中所提出的实现方法不一定是最优解,如果有其他更好的建议和想法,我衷心欢迎大家与我交流,一起学习进步!一、规则解读完整规则太多了,这里仅引入一些与视觉部分相关的内容。
水下机器人能够对水下管道上的吸附物进行检测报警及移除清理等,竞赛过程中水下机器人必须全程自主运行。赛场尺寸(长×宽×高)为3000×2000×600(mm)长方形水池,示意图如下:水下管道铺设在水池内,分浅水区、渐变区和深水区。管道上共设置若干(大于5、小于20)个吸附物,分布在管道各处。熟悉规则后,总结视觉任务如下:
管道巡线吸附物检测与识别二、实现思路1.管道巡线硬件采用openmv,寻迹对象为水下白色管道,思路与我的另一篇博文:https://blog.csdn.net/qq_39784672/article/details/121239435?spm=1001.2014.3001.5501中寻迹思路相仿,这里就不赘述了。
2.吸附物检测与识别吸附物在管道上布置方式如下图所示:吸附物为实心黑色物体,其截面为正方形、圆形两种,边长或直径尺寸限制在30~50mm范围,厚度不大于30mm。吸附物截面图如下:
上面为第十四届国际水中机器人大赛的比赛规则,工训的规则和这个相差不大。工训中要求检测并识别出吸附物形状;而水中则只需检测出即可,算是降低了难度。
吸附物检测与识别我们采用了两种方案:
(1)openmv手工特征我们尝试过许多特征,比如色块框像素占比、圆形和矩形查找等。
(2)k210目标检测模型通过制作吸附物的数据集训练yolo目标检测模型,最终部署到k210上进行预测输出吸附物类型和位置,完成检测和识别任务。相关实现方法参加我的另一篇博文:【实战】K210训练与部署YOLO目标检测模型
openmv代码最终比赛代码如下:
importsensor,image,time,pybimportmathfrompybimportUART,Timer#返回参数初始化tube_offset_angle=0#管道偏移角tube_offset_distance=0#管道偏移距离obstacle_shape=0#障碍物形状,取值规则:0:没有障碍物;1:圆形障碍物;2:矩形障碍物#调试参数tube_threshold=(30,100,-128,127,-128,127)#管道LAB阈值obstacle_threshold=(0,18,-7,26,-3,12)#障碍物LAB阈值timer_freg=25#定时器触发间隔(Hz)#定时器回调函数deftimeFunc(timer):time_flag=1#判断障碍块位置#return:0:left1:center2:right3:errordefgetPosition(o_b,t_b):#计算与管道中心的偏移x_offset=(o_b[0]+o_b[2]/2)-(t_b[0]+t_b[2]/2)#print(x_offset)ifabs(x_offset)=250andblob.pixels()max_size:max_blob=blobmax_size=blob.pixels()returnmax_blobsensor.reset()#初始化摄像头sensor.set_pixformat(sensor.RGB565)#格式为RGB565sensor.set_framesize(sensor.QQVGA)#使用QQVGA速度快一些,160*120sensor.skip_frames(n=800)#跳过800s,使新设置生效,并自动调节白平衡sensor.set_auto_gain(False)#关闭自动自动增益sensor.set_auto_whitebal(False)uart=UART(3,115200)#初始化串口通信参数clock=time.clock()#追踪帧率time_flag=0#定时标志位timer=Timer(2)#使用定时器2创建一个定时器对象timer.init(freq=timer_freg)#设置触发间隔timer.callback(timeFunc)#定义定时器回调函数scale=0#图像比例尺(mm/pixel)while(True):clock.tick()img=sensor.snapshot()#识别管道tube_blobs=img.find_blobs([tube_threshold],pixels_threshold=2000)iftube_blobs:tube_flag=1t_b=find_max(tube_blobs)tube_offset_angle=t_b[7]tube_offset_distance=t_b[5]scale=75/t_b[2]#print(scale)img.draw_rectangle(t_b[0:4])#绘制管道方向线#img.draw_line((t_b[5],t_b[6],t_b[5]+int(50*math.cos(t_b[7])),t_b[6]+int(50*math.sin(t_b[7]))),color=(255,255,255))#识别障碍物obstacle_blobs=img.find_blobs([obstacle_threshold],roi=(t_b[0:4]),pixels_threshold=100)ifobstacle_blobs:o_b=find_max(obstacle_blobs)img.draw_rectangle(o_b[0:4])ifabs((o_b[1]+o_b[3]/2)-60)35*scale:#print(o_b[3]-35*scale)obstacle_shape=2else:#print(o_b.density())ifo_b.density()