一、项目简介
基于机器视觉模块OpenMV采集车道、红绿灯、交通标志等模拟路况信息,实现一辆能车道保持、红绿灯识别、交通标志识别、安全避障以及远程WiFi控制的多功能无人驾驶小车。
赛道规格:
1、编程所需软件:
OpenMV:使用OpenMV官方的OpenMV IDE
ESP8266:使用Arduino官方的Arduino IDE
STM32:使用ARM官方的Keil uVision5(ARM版)
2、功能介绍:
OpenMV:主要是利用OpenMV进行路况信息(红绿灯、交通标志、车道)的采取,以及和STM32的通信。
ESP8266:主要是利用ESP8266与手机端进行远程的指令接收和数据交互,以及和STM32的通讯。
STM32:主要是通过ESP8266接收远程控制指令和处理路况信息,并根据这些指令数据进行实时的PID控制小车运动。
二、硬件系统
主要依靠机器视觉模块OpenMV通过图像处理的方式获取实时的路况信息,以及超声波传感器获取障碍物距离信息,得到的路况数据再通过串口传输到主控器STM32上面,STM32会将实时的路况信息处理成智能小车的运动控制指令,让智能小车实现红绿灯识别、交通标志识别以及车道实时保持的功能,还有STM32也会通过WiFi模块ESP8266与手机端进行路况数据和控制指令的远程交互。硬件系统框图如下:
下面简单介绍一下,整个系统用到的硬件模块。
具体的硬件电路连接框图如下:
三、软件系统
1、OpenMV中的路况识别算法实现
本项目的主要路况数据信息都是基于OpenMV摄像头获取的图像进行图像处理得到的。要实现智能小车的自动驾驶行为,最起码要让小车识别到红绿灯、交通标志以及车道,后续主控器才能根据这些路况数据信息控制小车的运动。关于机器视觉模块OpenMV的介绍,可以浏览《初探机器视觉模块OpenMV》这篇文章。
①红绿灯识别
主要是对摄像头每帧拍摄到的图像进行图像进行阈值处理,再进行判断出现的究竟是哪种红绿灯(红灯、绿灯、黄灯),然后再将这个判定结果和其他两个数据一起打包通过串口发送出去。
【程序流程图】
【主要程序】
###################################开始####################################
...
sensor.set_pixformat(sensor.RGB565) # 图片格式设为 RGB565彩色图
light_threshold = [(59, 100, 26, 127, -128, 127),(59, 100, -128, -40, -128, 127)]; #设置红绿灯阈值,默认为0无红绿灯 1红灯 2绿灯 4黄灯
...
#定义寻找色块面积最大的函数
def find_max(blobs):
max_size=0
for blob in blobs:
if blob.pixels() > max_size:
max_blob=blob
max_size = blob.pixels()
return max_blob
#主循环
while(True):
clock.tick() #追踪两个snapshots()之间经过的毫秒数
img = sensor.snapshot() #拍一张照片,返回图像
blobs = img.find_blobs(light_threshold,area_threshold=150); #找到红绿灯
cx=0;cy=0;LED_color=0; #变量定义
if blobs:
max_b = find_max(blobs); #如果找到了目标颜色
img.draw_rectangle(max_b[0:4]) #在Blob周围绘制一个矩形
#用矩形标记出目标颜色区域
img.draw_cross(max_b[5], max_b[6]) # cx, cy
img.draw_cross(160, 120) # 在中心点画标记
#在目标颜色区域的中心画十字形标记
cx=max_b[5];
cy=max_b[8];
img.draw_line((160,120,cx,cy), color=(127));
img.draw_string(cx, cy, "(%d, %d)"%(cx,cy), color=(127));
LED_color=cy; #红绿灯的阈值是数组里的cy(二进制)个
print(LED_color); #串行终端打印出 红绿灯序号数据
###################################结束####################################
②交通标志识别
主要是利用NCC(Normalized Cross Correlation)归一化互相关算法来进行交通标志的图像识别与匹配。
【NCC算法】
NCC算法的基本实现原理:主要是通过求两幅大小相近的图像的相关系数矩阵来判别两幅图像是否相关。假设需要识别的初始图片的大小为,摄像头拍摄到的图片S的大小为,其中的以为左上角点与大小相同的子图像为。具体的利用NCC算法实现计算图像相似度的方法如下:
【主要程序】
###################################开始####################################
...
sensor.set_pixformat(sensor.GRAYSCALE) #设置图片格式为灰度图
#导入图片模板
template1 = image.Image("/1.pgm") #直行
template2 = image.Image("/2.pgm") #向右转弯
template3 = image.Image("/3.pgm") #向左转弯
template4 = image.Image("/4.pgm") #停车让行
template5 = image.Image("/5.pgm") #鸣喇叭
#主循环
while (True):
clock.tick()
img = sensor.snapshot()
flag=0
ratio=0
#匹配1.pgm(直行)串行终端打印go,flag=1
r1 = img.find_template(template1, 0.70, step=4, search=SEARCH_EX)
if r1:
img.draw_rectangle(r1,color=(255,0,0))
print("go")
flag=1
img.draw_string(10, 10, "%.d"%flag)
#匹配2.pgm(向右转弯)串行终端打印right,flag=2
r2 = img.find_template(template2, 0.70, step=4, search=SEARCH_EX)
if r2:
img.draw_rectangle(r2,color=(0,255,0))
print("right")
flag=2
img.draw_string(10, 10, "%.d"%flag)
#匹配3.pgm(向左转弯)串行终端打印left,flag=3
r3 = img.find_template(template3, 0.70, step=4, search=SEARCH_EX)
if r3:
img.draw_rectangle(r3,color=(255,0,0))
print("left")
flag=3
img.draw_string(10, 10, "%.d"%flag)
#匹配4.pgm(停车让行)串行终端打印stop,flag=4
r4 = img.find_template(template4, 0.70, step=4, search=SEARCH_EX)
if r4:
img.draw_rectangle(r4,color=(255,255,0))
print("stop")
flag=4
img.draw_string(10, 10, "%.d"%flag)
#匹配5.pgm(鸣喇叭)串行终端打印beep,flag=5
r5 = img.find_template(template5, 0.70, step=4, search=SEARCH_EX)
if r5:
img.draw_rectangle(r5,color=(255,255,0))
print("beep")
flag=5
img.draw_string(10, 10, "%.d"%flag)
###################################结束####################################
③车道识别
主要通过OpenMV模块,识别并跟踪车道阈值,通过几何运算出小车与车道中线的角度(偏左为正、偏右为负),反馈出小车与车道的真实偏离情况(可量化),后续用于PID控制。
【主要程序】
###################################开始####################################
...
sensor.set_pixformat(sensor.RGB565) # 图片格式设为 RGB565彩色图
road_threshold = [(23, 0, -45, 19, -31, 28)]; #黑线道路
ROI = (0, 100, 320, 40)
...
#省略了识别车道边框函数
#偏移角度计算算法
def get_direction(left_blob, right_blob):
# 根据图像中的三块左中右的白色部分,计算出摄像头偏转角度
# ratio < 0 左拐,小车在车道偏右位置
# ratio > 0 右拐,小车在车道偏左位置
MAX_WIDTH = 320
# 调节theta来设置中间宽度的比重, theta越高ratio越靠近0
# 需要根据赛道宽度与摄像头高度重新设定到合适大小
theta = 0.01
# 这里的b是为了防止除数是0的情况发生, 设定一个小一点的值
b = 3
x1 = left_blob.x() - int(0.5 * left_blob.w()) #左边黑线中心x值
x2 = right_blob.x() + int(0.5 * right_blob.w()) #右边黑线中心x值
#车道信息计算
w_left = x1 #左边车道外宽度
w_center = math.fabs(x2 - x1) #车道中心x值
w_right = math.fabs(MAX_WIDTH - x2) #右边车道外宽度
#计算摄像头偏移角度
direct_ratio = (w_left + b + theta * w_center) / (w_left + w_right + 2 * b + 2 * theta * w_center) - 0.5
#返回摄像头偏移角度
return direct_ratio
#省略了可视化绘图函数
...
while(True): #主循环
clock.tick() #追踪两个snapshots()之间经过的毫秒数
img = sensor.snapshot() #拍一张照片,返回图像
blobs = img.find_blobs(road_threshold, roi=ROI, merge=True);
a=0;ratio=0;
if blobs:
left_blob, right_blob = get_top2_blobs(blobs)
if(left_blob == None or right_blob == None):
print("Out Of Range")
continue
else:
#画出车道左边线
img.draw_rectangle(left_blob.rect())
img.draw_cross(left_blob.cx(), left_blob.cy())
#画出车道右边线
img.draw_rectangle(right_blob.rect())
img.draw_cross(right_blob.cx(), right_blob.cy())
#可视化显示偏转角度
direct_ratio = get_direction(left_blob, right_blob)
draw_direct(img,direct_ratio)
ratio=int(math.degrees(direct_ratio)) #偏转角度转成弧度值
img.draw_string(10, 10, "%.d"%ratio) #帧缓冲区实时画出偏转角度
print(ratio) #串行终端打印偏转角度
img.draw_rectangle(ROI,color=(255, 0, 0)) #画出感兴趣区域
###################################结束####################################
2、基于ESP8266的远程控制平台实现
主要是利用点灯科技-Blinker物联网平台搭建控制APP的UI界面,以及调用Blinker的控制代码,实现智能小车控制指令的下发与路况数据的上传。
【远程控制平台UI界面】
【UI配置代码】
直接使用 点灯.blinker APP导入配置代码即可获得和我一样的UI布局。
{¨config¨{¨headerColor¨¨transparent¨¨headerStyle¨¨dark¨¨background¨{¨img¨¨assets/img/headerbg.jpg¨¨isFull¨«}}¨dashboard¨|{¨type¨¨btn¨¨ico¨¨fad fa-arrow-alt-up¨¨mode¨É¨t0¨¨前进¨¨t1¨¨文本2¨¨bg¨Ì¨cols¨Ë¨rows¨Ë¨key¨¨btn-go¨´x´Ì´y´Ï¨speech¨|÷¨clr¨¨#076EEF¨}{ßAßBßC¨fad fa-arrow-alt-down¨ßEÉßF¨后退¨ßHßIßJÌßKËßLËßM¨btn-back¨´x´Ì´y´¤CßO|÷ßPßQ¨lstyle¨É}{ßAßBßC¨fad fa-arrow-alt-right¨ßEÉßF¨右转¨ßHßIßJÌßKËßLËßM¨btn-right¨´x´Ï´y´ÒßO|÷ßPßQßUÉ}{ßAßBßC¨fad fa-arrow-alt-left¨ßEÉßF¨左转¨ßHßIßJÌßKËßLËßM¨btn-left¨´x´É´y´ÒßO|÷ßPßQßUÉ}{ßAßBßC¨fad fa-power-off¨ßEÉßF¨停车¨ßHßIßJÌßKËßLËßM¨btn-stoping¨´x´Ï´y´ÏßO|÷ßPßQßUÉ}{ßA¨tex¨ßF¨
标签:draw,img,小车,flag,blob,模拟系统,left,OpenMV
From: https://blog.51cto.com/u_15641375/6564004