背景介绍:
通过 《图像处理基础》能知道视觉就是在图片上找目标。通过《OpenMV 图片对象(目标识别基础)》能知道怎么找目标。

本篇继续这个话题,说说找目标是为了做什么。

提取赛道

线性回归方法的优点是能在视场中的任何位置找到线,缺点是慢。巡线设置为“灰度”、“QQQVGA”来加快速度,由于不跟踪颜色,所以不需要闭自动白平衡。

使用 histeq() 方法提高图像的对比度,以便接下来将图像二值化分离出赛道。

下面用 OpenMV IDE 提取赛道的灰度阀值,如下:

因为 Sugar 从柜子里翻出的老赛道充满了褶皱,所以噪点特别多。下面用 mean(2) 方法消个噪,再看下效果:

现在看上去好多了,接下来把图像通过 binary() 方法二值化,提取出赛道,如下:

赛道有点细,可以通过 erode(1) 让赛道粗一点,如下:

找赛道

1、车灯

小车前放车灯减小环境光对图像的影响,灯选用 WS2812 灯条(8 个灯珠)。WS2812 的驱动代码如下:

# -*- coding: utf-8 -*-import gc
import pybON  = 255
OFF = 0class WS2812:"""Driver for WS2812 RGB LEDs. May be used for controlling single LED or chainof LEDs.Example of use:chain = WS2812(spi_bus=1, led_count=4)data = [(255, 0, 0),    # red(0, 255, 0),    # green(0, 0, 255),    # blue(85, 85, 85),   # white]chain.show(data)Version: 1.0"""buf_bytes = (0x88, 0x8e, 0xe8, 0xee)def __init__(self, spi_bus=1, led_count=1, intensity=1):"""Params:* spi_bus = SPI bus ID (1 or 2)* led_count = count of LEDs* intensity = light intensity (float up to 1)"""self.led_count = led_countself.intensity = intensity# prepare SPI data buffer (4 bytes for each color)self.buf_length = self.led_count * 3 * 4self.buf = bytearray(self.buf_length)# SPI initself.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=3200000, polarity=0, phase=1)# turn LEDs offself.show([])def show(self, data):"""Show RGB data on LEDs. Expected data = [(R, G, B), ...] where R, G and Bare intensities of colors in range from 0 to 255. One RGB tuple for eachLED. Count of tuples may be less than count of connected LEDs."""self.fill_buf(data)self.send_buf()def send_buf(self):"""Send buffer over SPI."""self.spi.send(self.buf)gc.collect()def update_buf(self, data, start=0):"""Fill a part of the buffer with RGB data.Order of colors in buffer is changed from RGB to GRB because WS2812 LEDhas GRB order of colors. Each color is represented by 4 bytes in buffer(1 byte for each 2 bits).Returns the index of the first unfilled LEDNote: If you find this function ugly, it's because speed optimisationsbeated purity of code."""buf = self.bufbuf_bytes = self.buf_bytesintensity = self.intensitymask = 0x03index = start * 12for red, green, blue in data:red = int(red * intensity)green = int(green * intensity)blue = int(blue * intensity)buf[index] = buf_bytes[green >> 6 & mask]buf[index+1] = buf_bytes[green >> 4 & mask]buf[index+2] = buf_bytes[green >> 2 & mask]buf[index+3] = buf_bytes[green & mask]buf[index+4] = buf_bytes[red >> 6 & mask]buf[index+5] = buf_bytes[red >> 4 & mask]buf[index+6] = buf_bytes[red >> 2 & mask]buf[index+7] = buf_bytes[red & mask]buf[index+8] = buf_bytes[blue >> 6 & mask]buf[index+9] = buf_bytes[blue >> 4 & mask]buf[index+10] = buf_bytes[blue >> 2 & mask]buf[index+11] = buf_bytes[blue & mask]index += 12return index // 12def fill_buf(self, data):"""Fill buffer with RGB data.All LEDs after the data are turned off."""end = self.update_buf(data)# turn off the rest of the LEDsbuf = self.bufoff = self.buf_bytes[0]for index in range(end * 12, self.buf_length):buf[index] = offindex += 1def on():data = []for i in range(0,8):data.append((ON, ON, ON))WS2812(spi_bus=2, led_count=8).show(data)def off():data = []for i in range(0,8):data.append((OFF, OFF, OFF))WS2812(spi_bus=2, led_count=8).show(data)

将上述代码放置在 ws2812.py 文件中供其他程序调用。

2、找车道并画线
(1) 首先了解线性回归算法 API 接口 image.get_regression(阀值) 函数:

此函数对图像所有阀值像素进行线性回归计算,返回一个 image.line 对象,可以用 image.draw_line() 画出返回的线条。

对于线性回归使用的最小二乘法这里不需要深究,但需要了解返回值的意义。首先来看两个实验现象:

通过这两个现象,能够总结出 image.get_regression(阀值) 返回值的意义,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ug9vvhL0-1602815269138)(http://weipeng_su.gitee.io/img/19_OpenMV/line_track_12.jpg)]

当我们了解这个规律后,就可以这样算出轨道的方向和角度:

def line_to_theta_and_dir(line):angle_deg = 0direct = 0if line.theta() > 90:angle_deg = 180 - line.theta()direct = 1elif line.theta() < 90:angle_deg = line.theta()if line.theta() == 0:direct = 0else:direct = -1return (direct, angle_deg)

目前找出赛道的完整程序如下:

import sensor, image, time, mathGRAYSCALE_THRESHOLD = (42, 255)
MAG_THRESHOLD = 4def line_to_theta_and_dir(line):angle_deg = 0direct = 0if line.theta() > 90:angle_deg = 180 - line.theta()direct = 1elif line.theta() < 90:angle_deg = line.theta()if line.theta() == 0:direct = 0else:direct = -1return (direct, angle_deg)def line_track(track_color):direct = 0angle_deg = 0line_magnitude = 0img = sensor.snapshot()img.mean(2)img.binary([GRAYSCALE_THRESHOLD])img.crop([0,15,80,60])img.erode(1)line = img.get_regression([track_color], robust=True)if line and (line.magnitude() >= MAG_THRESHOLD):line_magnitude = line.magnitude()if line_magnitude >= MAG_THRESHOLD:line_color = 0if track_color[0] == 0:line_color = 255img.draw_line(line.line(), line_color)direct, angle_deg = line_to_theta_and_dir(line)return direct, angle_deg, line_magnitude

关注作者

欢迎扫码关注我的公众号MultiMCU EDU

提示:在公众号“关于我”页面可加作者微信好友。

喜欢本文求点赞,有打赏我会更有动力。

OpenMV 线性回归巡线之一:赛道提取相关推荐

  1. openmv 飞机巡线

    2017.8.7.11.03 参考Open*V机器人巡线例程,find_line例程,进行了简单修改.做成了飞机巡线. 希望同各位大佬一起学习一起讨论

  2. OpenMV:14巡线小车

    文章目录 追小球的小车 巡线小车 这个例子展示了在OpenMV Cam上使用get_regression()方法获得ROI的线性回归.使用这种方法,可以轻松让机器人跟踪所有指向相同大致方向的线. 本例 ...

  3. 根据星瞳科技openmv巡线小车所改进的巡线方案

    首先看一下星瞳科技的巡线方案(附上其开源源码): THRESHOLD = (5, 70, -23, 15, -57, 0) # Grayscale threshold for dark things. ...

  4. 视觉识别数字、十字路口和T字路口,巡线于一体的基于openmv的解决方案(2021年电赛f题)

    普通二本生(大二)没获奖,因为驱动方面和视觉协同问题没有做好(驱动方面跑太快,速度降不下来)只跑了最初级的,这个文章就是去记录一下我的成长过程吧. 目录 1.使用神经网络来进行识别 2.使用模板匹配来 ...

  5. 2021电赛F题之openmv巡线(附代码)

    效果展示: 出错解决方法 openmv数字识别源代码–gitee 通过使用不同阈值的方法可以得到当前区域中什么区域有红线,对于电控而言作用类似于红外对管,之后电控通过逻辑判断如何运动,这就是我们队伍目 ...

  6. OPENMV的学习(三)巡线

    存储文件 插入sd卡,会将默认储存地址flash改为sd卡. image.save("/example.jpg") 串口通信 传输面积最大的色块的坐标 # Blob Detecti ...

  7. 基于Openmv H7 Plus 的红色巡线+十字路口+多数字识别算法

    一.串口通信 由于是采用命令集的方式控制openmv,摄像头不需要接收太多的数据,我采用的是判断串口接收的长度来区分命令集.flag为接收数据的长度,通过发送不同长度数据来改变openmv的工作模式 ...

  8. k210的简单PID巡线

    目录 1.前言 2.简介 3.代码讲解 1.调用自带的库文件 2.将I/O18和 I/O19分别注册为UART1_TX和UART1_RX功能并设置串口 3.向STM32F103单片机发送数据包 4.基 ...

  9. 深度神经网络控制的巡线智能车

    ■ 简介 Michal Nand 在网站 HACKADAY.IO 上通过博文 Motoku Uprising Deep Neural Network 介绍了他利用卷积神经网络来帮助控制巡线智能车更加平 ...

最新文章

  1. Docker镜像优化
  2. leetcode_1. Two Sum
  3. 如何入门自动控制理论
  4. linux hal-get-property进程说明,Android HAL property_get() 函数用法
  5. 基于vb的mysql管理系统代码_VB ACCESS高校财务管理系统[论文 源代码 可执行程序]...
  6. HTTP请求方式和幂等性
  7. mysql获取今天的最后一秒_Oracle取得当天0时0分0秒和23时59分59秒
  8. 解决:samba 无法访问,您可能没有权限使用网络资源,请与这台服务器管理员联系 指定的网络名不可用
  9. An assembly specified in the application dependencies manifest
  10. 分布式计算、云计算与大数据第十章
  11. 7-11 哥德巴赫猜想
  12. TMS和WMTS大概对比
  13. python之用scapy分层解析pcap报文(Ethernet帧、IP数据包、TCP数据包、UDP数据包、Raw数据包)
  14. 20款精美APP和Web设计模板素材(附演示链接)
  15. python制作天气预报软件(UI界面)
  16. 利用jsoup爬取百度网盘资源分享连接(多线程)
  17. Oracle基础之保留字和关键字
  18. 【问底】王帅:深入PHP内核(二)——SAPI探究
  19. One Note插件——gem for onenote的安装
  20. mavn学习笔记(未整理)

热门文章

  1. 现今中国大学生就业现状
  2. 【产品设计】有了创意,如何从零开始搭建一套产品模型
  3. Excel函数--SUM计算累计销量
  4. 数字化工厂正在塑造制造业未来
  5. 你知道DAU、MAU、PCU、DAU、ARPU、KPI是指什么?
  6. Chrome扩展学习Demo(三):将浏览器地址栏的网址转换为二维码
  7. 记录一下:老衲的py路程 mac下的tkinter小应用
  8. 为什么说互联网的下半场,是中国年轻人的新机会?
  9. 会议室日程安排问题(python贪心算法)
  10. 云南师范大学计算机考研资料汇总