我们花费了四天时间打了一场21年的电赛改编题——智能送药小车。虽然结果不尽人意,但这是我学习32以来第一次正式的打比赛,对我来说要学习的东西,所增长的经验真的特别多(虽然基本上都是学长在出力~)下来我就把关于这次比赛的感悟和大家分享一下。
一、OpenMV寻迹
我们使用OpenMV进行寻迹。思路就是先对图像进行二值化处理,只让OpenMV识别出红线,然后通过线性回归方法检测出直线。通过计算出直线的平移偏移量和旋转偏移量,然后带入pid算法中来控制小车进行巡线。
#pid巡线前进
def lookfor_line():
# 使用PID算法计算控制信号
rho_output = rho_pid.get_pid(直线平移偏移量, 1)
theta_output = theta_pid.get_pid(直线旋转偏移量, 1)
output = rho_output + theta_output
#print("kkkkkkkkkkkkkk", end="")
#print(output)
# 根据PID输出调整小车的速度
output = output * 2
car.run(80+ output, 80 - output)
# 计算直线的平移偏移量(直线中点到图像中心的距离)
直线平移偏移量 = abs(line.rho()) - img.width() / 2
# 计算直线的旋转偏移量(直线与垂直方向的夹角)
if line.theta() > 90:
直线旋转偏移量 = line.theta() - 180
else:
直线旋转偏移量 = line.theta()
# 如果直线的强度(长度)足够大,则认为是有效直线,需要控制小车
if stats.mean() > 3:
lookfor_line()
二、OpenMV检测路口
识别数字的摄像头无非就发送三种数据,要么目标药房在左,要么目标药房在右,要么没识别到直接前进。下面的摄像头只负责检测到路口然后执行上面摄像头发下来的操作即可,不必区分十字路口还是T字路口。
我们检测路口的思路也很简单,只要判断红色区域(二值化之后是白色区域)的面积突然增大即可。我们的摄像头在一般巡线的时候红色区域的面积在15左右,当有路口出现的时候,面积会到23左右。
stats = img.get_statistics()
#遇到了路口
if stats.mean()>18:
#执行相关逻辑代码
三、OpenMV数字识别
我们使用的是OpenMV的多模板匹配。效果还行。
模版的采集:
· 就是先将车搭好,然后让车开到指定地点,就最好是后面的T字路口处,让T字路口的那四张照片全部落在OpenMV的正中央,将这些数字的几种形态全部拍摄成模版。可以将数字分为两大类。1~2,3~8。因为1~2是固定路线,所以只要拍摄正脸照用来发车前识别就行。3~8可以分为左边,最左边,右边,最右边和正面五中情况。所以我们一共拍摄了32张模板,然后将模板转化为pgm格式,像素大小为35*35。因为不能超过openmv的像素大小。35*35的像素我们感觉识别速度和准确率都还行,官方给的建议是不超过60*80。
我们是用电脑截图,然后改像素转格式。截图时用的代码:
import sensor,time,image
#重置传感器
sensor.reset()
sensor.set_contrast(1)#设置对比度
sensor.set_gainceiling(16)#设置增益上限
sensor.set_framesize(sensor.QQVGA)#设置图像分辨率为 QQVGA
sensor.set_pixformat(sensor.GRAYSCALE)#设置图像格式为灰度
#sensor.set_windowing(0, 40, 160, 40)#设置窗口大小,后面ROI设置也会以这个为新的基准
# 拍摄图像并保存
while (1):
img = sensor.snapshot()
time.sleep_ms(10)
多模板匹配:
多模版匹配其实就是用多个模版调用模板匹配函数 find_template 来进行模板匹配。如果进行多模板匹配时检测不到模板,可以适当降低感兴趣区域面积 roi ,使用EX识别,减少 threshold 的值等。如果错误率太高可以增加 threshold 的值,增加模板等。