利用blob算法对信号灯进行提取检测,控制TB3完成对信号灯的起停动作!
读书须有胆识,有眼光,有毅力,
胆识二字拆不开,要有识必敢有自己意见,即使一时与前人不同亦不妨,
前人能说得我服,是前人是,前人不能服我,是前人非,
人心之不同如其面,要脚踏实地,不可舍己来云人
——林语堂
订阅话题
同车道线检测《TB3_Autorace之车道线检测》程序一样,我们这里接收未经透视变换的原始图像信息/camera/image_compensated
以及信号灯检测结束信号/control/traffic_light_finished
。
1 | if self.sub_image_type == "compressed": |
发布话题
发布检测到的红黄绿三色信号灯信息/detect/image_output_sub
、检测开始信号/control/traffic_light_start
、检测状态信号/detect/traffic_light_stamped
以及速度控制信号/control/max_vel
。
1 | if self.pub_image_type == "compressed": |
设定检测状态
这里我们利用python的枚举操作将信号灯检测封装为几个不同状态,根据不同状态特点我们对速度进行相应的控制。1
2
3
4
5
6
7self.StepOfTrafficLight = Enum('StepOfTrafficLight',
'searching_traffic_light
searching_green_light
searching_yellow_light
searching_red_light
waiting_green_light
pass_traffic_light')
设定颜色阈值
对红黄绿三色信号灯设定HSL阈值范围,用以对掩膜后的图像进行信号灯的颜色提取,可通过将提取的图像打印到屏幕上以便调整阈值范围。
1 | self.hue_red_l = rospy.get_param("~detect/lane/red/hue_l", 0) |
格式转换
视频格式是一帧一帧的图像信息,想要对每一帧图像进行处理就要先设置订阅图像的帧速率,根据计算机处理性能来设定帧速率,这里我们设置成10fps。将订阅到图像信息的格式转换成OpenCV库能够处理的格式。代码封装如下:
1 | def cbGetImage(self, image_msg): |
信号灯提取
同《TB3_Autorace之车道线检测》中采用的方法一样,利用颜色阈值对颜色进行提取,返回掩膜之后的图像。
1 | def fnMaskRedTrafficLight(self): |
信号灯检测
利用OpenCV库集成的cv2.SimpleBlobDetector斑点检测器对图像中的信号灯状态进行检测。Blob分析(Blob Analysis)是对图像中相同像素的连通域进行分析,该连通域称为Blob。Blob分析可为机器视觉应用提供图像中的斑点的数量、位置、形状和方向等信息。
该算法通过参数创建过滤器过滤斑点:通过像素阈值过滤;通过斑点面积过滤;通过圆性(4×pi×area/perimeter**2)过滤;通过凸性(斑点面积/斑点凸包面积)过滤;通过惯性比(Inertia Ratio)过滤,一个形状有多长(圆1,椭圆0-1.直线0)对信号灯进行检测,将检测出的斑点用红色圆包围标识,根据距离信号灯的远近设定区域范围,求出斑点中心坐标,根据斑点是否在设定范围内以及信号灯颜色来指定5个状态status,进而实现减速、停车动作。返回状态编号。代码封装如下:
1 | def fnFindCircleOfTrafficLight(self, mask, find_color): |
运动控制
将掩膜后的图像进行高斯滤波处理,对于检测绿色信号灯,绿色计数加1;检测黄色信号灯,黄色计数加1;检测红色信号灯,较远距离,红色计数加1,较近距离,停止计数加1(为了避免急停,将检测红灯分为远近两种状态)。根据各个状态计数值,发布max_vel速度控制命令,控制小车根据信号灯指示运动。代码封装如下:
1 | cv_image_mask = self.fnMaskGreenTrafficLight() |
至此,已完成所有信号灯检测工作。实现控制TB3机器人根据信号灯指示完成起停动作。
经验分享
1.blob算法还可以添加通过惯性比(Inertia Ratio)检测因子进行过滤,缺点是处理速度过慢,要对整个区域作逐点扫描。
2.在利用cv2.SimpleBlobDetector检测器对信号灯进行检测之前要对图像进行取反工作,突出斑点。
3.接收图像信息的帧速率要根据主机性能进行设置,切勿设置过慢导致漏帧现象发生。