2023人形全能赛openmv巡线代码
- openmv
import sensor, image, time, math
from pyb import LED, millis, UART
class RobotControl:
flag = 0 # 代表是否使用更新的区域来进行下一次检测
def __init__(self):
# 获取三种颜色的灯
self.red_led = LED(1)
self.green_led = LED(2)
self.blue_led = LED(3)
# 图像翻转
sensor.reset()
#sensor.set_vflip(True)
#sensor.set_hmirror(True)
sensor.set_pixformat(sensor.RGB565) # 读入彩色图片
sensor.set_framesize(sensor.QQVGA) # 160×120
sensor.skip_frames(time=2000) # 跳过2000张图片
# 线的阈值
self.THRESHOLD = (29, 0, 61, -86, -69, 55) # 黑色
self.red_threshold = (0, 100, 19, -62, -81, 61)
# 通信初始化
self.uart = UART(3, 19200) # 注意波特率
# 计算差值
self.middle = 0
# 每次检测区域 (6块) (x, y, w, h)
self.init_roi = [(5, 50, 70, 10), (85, 50, 70, 10),
(5, 70, 70, 10), (85, 70, 70, 10),
(5, 90, 70, 10), (85, 90, 70, 10), ]
self.roi = []
self.py = 5 # 找的正方形的竖直偏差
self.img = None # 每次的图片存在这,方便操作
self.count_turn_left = 0
self.is_cross_barr = 0
# 关灯
def close_rgb(self):
self.red_led.off()
self.green_led.off()
self.blue_led.off()
# 开白灯
def while_rgb(self):
self.close_rgb()
self.red_led.on()
self.green_led.on()
self.blue_led.on()
# 开红灯
def red_rgb(self):
self.close_rgb()
self.red_led.on()
# 开绿灯
def green_rgb(self):
self.close_rgb()
self.green_led.on()
# 开蓝灯
def blue_rgb(self):
self.close_rgb()
self.blue_led.on()
# 数据发送
def send_to_arduino(self, mes):
print("send_message:", mes) # 调试用
#time.sleep(0.1)
send_str = "{" + str(mes) + "&}"
self.uart.write(send_str)
# 数据接收
def recv_from_arduino(self):
recv = self.uart.read()
if recv:
return recv
else:
return None
# 获取边界点(6个)
def get_dot(self, roi):
most_pixels = 0
max_x = 0
if self.img:
blob0 = self.img.find_blobs([self.THRESHOLD], roi=roi, pixels_threshold=2, area_threshold=2, merge=True)
if blob0:
for n in range(len(blob0)):
if blob0[n].pixels() > most_pixels:
most_pixels = blob0[n].pixels()
max_x = n
# 将矩形标出
self.img.draw_rectangle(blob0[max_x].x(), blob0[max_x].y(), blob0[max_x].w(), blob0[max_x].h(),
color=(0, 0, 255), thickness=1, fill=False)
# 将矩形中点标出
self.img.draw_cross(blob0[max_x].x() + int(blob0[max_x].w() / 2), blob0[max_x].y() + int(
blob0[max_x].h() / 2), color=(0, 0, 255), size=1, thickness=1)
return blob0[max_x].x() + int(blob0[max_x].w() / 2), \
blob0[max_x].y() + int(blob0[max_x].h() / 2) # 矩形中心
else:
return 0
else:
return 0
def get_dx(self):
left_dot_dic = {}
right_dot_dic = {}
middle_dot = []
# 检测区域动态更新
if not RobotControl.flag:
RobotControl.flag = 1
roi = self.init_roi
else:
roi = self.roi
roi = self.init_roi
# 获取边界坐标
for i in range(6):
roii = roi[i]
dot = self.get_dot(roii)
if dot:
dot = list(dot)
if 50 <= dot[1] <= 59:
dot[1] = 55
if 70 <= dot[1] <= 79:
dot[1] = 75
if 90 <= dot[1] <= 99:
dot[1] = 95
if i % 2 == 0:
left_dot_dic[dot[1]] = dot[0]
else:
right_dot_dic[dot[1]] = dot[0]
# 获取中点坐标
for y1, x1 in left_dot_dic.items():
if right_dot_dic.get(y1, -1) != -1:
x2 = right_dot_dic.get(y1, -1)
middle_dot.append(((x1 + x2) // 2, y1))
# 将路中点标出
self.img.draw_cross((x1 + x2) // 2, y1, color=(0, 255, 0), size=1, thickness=1)
# 中点排个序
middle_dot = sorted(middle_dot, key=lambda x: x[1], reverse=True)
# 清空变动的坐标列表
self.roi = []
# 若三个中点都找到
if len(middle_dot) == 3:
numy = 3
# 更新下一个区域
for y1, x1 in left_dot_dic.items():
x2 = right_dot_dic.get(y1, -1)
if x1 >= 5:
x1 -= 5
else:
x1 = 0
if x2 >= 160 - 70 - 1:
x2 = 89
self.roi.append((x1, y1 - self.py, 60, 10))
self.roi.append((x2, y1 - self.py, 60, 10))
# 获取dx middle_x并返回
dx = middle_dot[0][0] - middle_dot[2][0]
middle_x = (middle_dot[0][0] + middle_dot[1][0] + middle_dot[2][0]) // 3
elif len(middle_dot) == 2:
numy = 2
RobotControl.flag = 0
dx = middle_dot[0][0] - middle_dot[1][0]
middle_x = (middle_dot[0][0] + middle_dot[1][0]) // 2
elif len(middle_dot) == 1:
numy = 1
RobotControl.flag = 0
dx = 0
try:
middle_x = middle_dot[0][0]
except:
middle_x = 80 # 如果没找到中线的话返回中线值即可
if len(right_dot_dic) >= len(left_dot_dic):
num_list = right_dot_dic.values()
num_list = sorted(num_list, reverse=True) # 降序
else:
num_list = left_dot_dic.values()
num_list = sorted(num_list, reverse=True) # 降序
if len(num_list) == 1:
dx = 0
else:
dx = num_list[0] - num_list[-1]
# 没有找到一个中点的情况,需要进行更多的判断
else:
RobotControl.flag = 0
numy = 0
middle_x = 0
if not left_dot_dic and not right_dot_dic:
dx = -10 # 一个点都看到
elif not left_dot_dic: # 没有左边的边界
num_list = right_dot_dic.values()
num_list = sorted(num_list, reverse=True) # 降序
if len(num_list) == 1:
dx = -1 # 只有右边边界的一个点
else:
dx = -6 # 右边边界有两个及以上个点
print(num_list)
middle_x = num_list[0] - num_list[-1]
elif not right_dot_dic: # 没有右边的点
num_list = left_dot_dic.values()
num_list = sorted(num_list, reverse=True) # 降序
if len(num_list) == 1:
dx = -2 # 只有左边的一个点
else:
dx = -7 # 左边边界有两个及以上个点
middle_x = num_list[0] - num_list[-1]
elif len(right_dot_dic) == 2 and len(left_dot_dic) == 1:
dx = -3 # 右边两个点,左边一个点
elif len(right_dot_dic) == 1 and len(left_dot_dic) == 2:
print("right_dot_dic:", right_dot_dic)
print("left_dot_dic:", left_dot_dic)
dx = -4 # 左边两个点,右边一个点
else:
print("right_dot_dic:", right_dot_dic)
print("left_dot_dic:", left_dot_dic)
dx = -5
return dx, middle_x, numy
def get_distance(self):
blobs = self.img.find_blobs([self.red_threshold], invert=True)
max_pix = 0
count = -1
if blobs:
local_i = -1
for ele in blobs:
count += 1
if ele[4] > max_pix:
max_pix = ele[4]
local_i = count
if local_i >= 0:
b = blobs[local_i]
self.img.draw_rectangle(b[0:4]) # 画正方形
self.img.draw_cross(b[5], b[6]) # 画十字
cx = b.cx()
cy = b.cy() # 获取像素大小
pixels = b.pixels()
rotation = math.degrees(b.rotation()) - 90
return cx, cy, pixels, rotation
return 0, 0, 0, 0
def send_next_move_order(self):
# define GO_STRAIGHT 2 // 直行
# define GO_LITTLE_STRAIGHT 3 // 小直行
# define GO_MICRO_STRAIGHT 4 // 小小直行
# define GO_RIGHT 5 // 右转
# define GO_LITTLE_RIGHT 6 // 小右转
# define GO_LEFT 7 // 左转
# define GO_LITTLE_LEFT 8 // 小左转
# define GO_LEFT_TRANSVERSE 9 // 原地左胯一步
# define GO_RIGHT_TRANSVERSE 10 // 原地右胯一步
# define GO_OBSTACLE 11 // 越障
self.img = sensor.snapshot()
dx, middle_x, numy = self.get_dx() # dx 中点偏差 middle_x 中点的中间值(算出来的) numy 中间点的个数
print("dx, middle_x, numy:", dx, middle_x, numy)
# 若有三个中点, 则只用dx斜率判断
if numy == 3:
# 直行
if -1 <= dx <= 4:
self.send_to_arduino(2) # 直行
elif dx <= -2:
# 在赛道偏外侧,还是能直行
if middle_x <= 80:
self.send_to_arduino(2) # 直行
else:
self.send_to_arduino(5) # 右转
elif dx >= 10:
if middle_x <= 70:
self.send_to_arduino(8) # 小左转
else:
self.send_to_arduino(2) # 直走
elif 5 <= dx <= 10:
if middle_x >= 90:
self.send_to_arduino(5) # 右转
elif 82 <= middle_x <= 89:
self.send_to_arduino(2) # 直行
else:
self.send_to_arduino(7) # 左转
elif numy == 2:
if middle_x >= 85:
self.send_to_arduino(2) # 直行
else:
self.send_to_arduino(8) # 小左转
elif numy == 1:
if dx >= 10:
if 86<=middle_x<=100:
self.send_to_arduino(5) # 右转
else:
self.send_to_arduino(7) # 左转
elif dx >= 5:
if middle_x>=90:
self.send_to_arduino(2) # 直行
else:
self.send_to_arduino(8) # 小左转
else:
self.send_to_arduino(2) # 直行
#if middle_x <= 85:
#self.send_to_arduino(8)
#elif middle_x >= 105:
#self.send_to_arduino(5)
#else:
#self.send_to_arduino(2)
else: # 没有扫到正常的中点 dx有 -1 -2 -3 -4 -5 -6 -7 -10
if dx == -1: # 只有右边一个点
self.send_to_arduino(9) # 左胯一步
elif dx == -2: # 只有左边的一个点
self.send_to_arduino(10) # 右胯一步
elif dx == -3: # 右边两个点,左边一个点
self.send_to_arduino(8) # 小左
elif dx == -4: # 左边两个点,右边一个点
self.send_to_arduino(5) # 右转
elif dx == -6: # 右边边界有两个及以上个点
if middle_x >= 20:
self.send_to_arduino(7) # 左转
elif middle_x >= 15:
self.send_to_arduino(8) # 小左转
else:
self.send_to_arduino(9) # 原地左胯一步
#self.send_to_arduino(10) # 原地右胯一步
#self.send_to_arduino(5) # 原地右转
elif dx == -7:
if 5<=middle_x <= 20:
self.send_to_arduino(5) # 右转
elif middle_x >= 21:
self.send_to_arduino(7) # 左转
else:
self.send_to_arduino(2) # 直行
elif dx == -5:
self.send_to_arduino(7) # 左转
elif dx == -10:
self.send_to_arduino(8)
def find_line_and_red(self):
# define GO_STRAIGHT 2 // 直行
# define GO_LITTLE_STRAIGHT 3 // 小直行
# define GO_MICRO_STRAIGHT 4 // 小小直行
# define GO_RIGHT 5 // 右转
# define GO_LITTLE_RIGHT 6 // 小右转
# define GO_LEFT 7 // 左转
# define GO_LITTLE_LEFT 8 // 小左转
# define GO_LEFT_TRANSVERSE 9 // 原地左胯一步
# define GO_RIGHT_TRANSVERSE 10 // 原地右胯一步
# define GO_OBSTACLE 11 // 越障
# 20 // 小小小直行
# 18 // 原地右转
# 19 // 原地左转
# 99 小小直行+越障
# 98 左转+右胯
self.img = sensor.snapshot()
cx, cy, pixels, rotation = self.get_distance()
if pixels <= 450 and self.is_cross_barr:
if self.is_cross_barr:
if cx>130:
self.is_cross_barr = 0
self.send_to_arduino(97)
return
self.send_next_move_order()
else:
self.is_cross_barr = 1
# 先判断距离,再判断朝向,最后判断左右距离
if cy <= 75:
self.send_to_arduino(2)
elif cy <= 95:
self.send_to_arduino(20)
else:
if rotation >= 0 or rotation <= -85:
self.count_turn_left += 1
if self.count_turn_left == 2:
self.send_to_arduino(98)
else:
self.send_to_arduino(19)
elif -79 <= rotation <= 0:
self.send_to_arduino(18)
else:
if 15 <= cx <= 75:
self.send_to_arduino(99)
elif cx > 76:
self.send_to_arduino(10)
else:
self.send_to_arduino(9)
# 运行入口
def run(self):
self.while_rgb()
while 1:
order = self.recv_from_arduino()
# self.img = sensor.snapshot()
# print(self.get_distance())
sensor.snapshot()
#self.send_next_move_order()
if order:
order = order.decode("utf-8")
print("接受消息:", order)
if order == "g":
self.send_next_move_order()
if order == "r":
self.find_line_and_red()
if __name__ == '__main__':
robot = RobotControl()
robot.run()
2023人形全能赛openmv巡线代码的更多相关文章
- 画线代码V1.0.0
画线代码: 最终效果图: 优点: 1.效果还行,计算量也不大(就一点2维直线一般式能有多少运算量). 缺点: 1.每条线怎么也是建模,可能会有点开销. 2.编辑起来很是麻烦. 代码部分: /***** ...
- 巡风代码架构简介以及Flask的项目文件结构简介
一.巡风: 巡风是一款什么东西,想必安全同行都不陌生吧.用它作为内网漏洞扫描管理架构是一种很好的选择,扫描快,开源,还可自己编写符合规则的POC直接放入相应目录来扩展.今天下午趁着有点时间捋了一下巡风 ...
- CSS 定义上划线、下划线、删除线代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 开启A20线(部分译)
开启A20线 在查看或编写操作系统内核时一定会遇到A20线这个问题.本人对此一直都是似懂非懂的,查了些资料,决定弄明白于是有了这篇文章.其中前一部分是翻译一篇外国博文,但光有这篇文章依旧不能清楚地说明 ...
- NYOJ 123 士兵杀敌4-树状数组的插线求点
士兵杀敌(四) 时间限制:2000 ms | 内存限制:65535 KB 难度:5 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编 ...
- arcgis jsapi接口入门系列(4):用代码在地图画点线面
PS:用代码画点这样写是为了跟后面的用鼠标画点线面区分出来 画点 drawPointGraphic: function () { //点有多种样式:一般的点,显示文字,显示图片 //一般的点 let ...
- C#代码实现矢量画图
原文:C#代码实现矢量画图 版权声明:本文为博主原创文章,转载请附上链接地址. https://blog.csdn.net/ld15102891672/article/details/80275969 ...
- WPF在圆上画出刻度线
思路 我们可以使用Ellipse先画出一个圆当背景,然后用Canvas再叠加画上刻度线,就能得到如下的效果 我们先用Ellipse画一个橙色的圆,然后将Canvas的宽度和高度绑定到Ellipse的宽 ...
- HarmonyOS 润和 HiSpark开发套件 免费领!
让人期盼已久的HarmonyOS 2.0终于在9月10日正式上线啦! 这是一件让众多开发者关注的大事件! 相信不少开发者都已经迫不及待的想上手实操了, 为了满足大家的好奇心, 也希望能有更多开发者了解 ...
- 基于HT for Web的3D呈现A* Search Algorithm
最近搞个游戏遇到最短路径的常规游戏问题,正巧看到老同事写的3D机房最短路径巡线文章,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.c ...
随机推荐
- kafka开启kerberos认证详细步骤
一.kerberos安装部署 kerberos的基本原理不做过多介绍了,可自行查阅:本文主要介绍kerberos的安装及使用;使用到的软件版本:系统:Red Hat Enterprise Linux ...
- cypress 在 typescript 项目中报错找不到 'tslib'
原文链接:https://blog.jijian.link/2020-08-11/cypress-typescript-cannot-find-module-tslib/ cypress 在 type ...
- nginx 根据 URL 参数引入不同的文件
同步发布:https://blog.jijian.link/2020-06-30/nginx-import-file/ 编程世界中各种奇奇怪怪的需求都有,本次遇到一个需求:根据URL参数判断,包含 x ...
- 如何在 Github 上获得 1000 star?
作为程序员,Github 是第一个绕不开的网站.我们每天都在上面享受着开源带来的便利,我相信很多同学也想自己做一个开源项目,从而获得大家的关注.然而,理想很丰满,现实却是开发了很久的项目仍然无人问津. ...
- CDH6.3.2下安装部署Qualitis数据质量分析的计算服务Linkis1.3.2
快速搭建Qualitis手册 一.基础软件安装 Gradle (4.6) MySQL (5.5+) JDK (1.8.0_141) Linkis(1.0.0+), 必装Spark引擎.如何安装Link ...
- VS Code Runner 插件配置
VS Code Runner 插件配置 Code Runner插件是一个小而美的插件,可以很方便的运行一些简单的代码文件. 本篇博文记录一些相关的环境配置. 设置C++编译标准 这里可以设置默认的C+ ...
- C#元数据的概念,以及一个使用了lambda表达式的简单例子
先看一个例子 假设你写了一个 C# 类库 MathUtils.dll: public class Calculator { public int Add(int a, int b) => a + ...
- 【Java】Java实现简单异或加密
Java实现简单异或加密 零.需求 在做一个简单的Web项目,需要把账号密码以Cookie的形式存储到浏览器中记住,不能直接明文,故需要一种简单的加密方式,想到了异或加密. 壹.实现 /** * 异或 ...
- Dubbo学习系列之十九(Apollo分布式部署)
说一个人是武林高手:十八般武艺,样样精通!如今,后端技术层出不穷,让人眼花缭乱,如果看官不能达到样样精通,至少 拿起方天画戟能耍几下才行,比如削个苹果.言归正传,配置中心属于基础设施,当然必须玩得溜, ...
- C# using 别名
场景重现 当using的多个库出现类名重复的情况时... 解决办法 使用类的完全限定名称,例如: // 不需要using,避免using名称重复导致的异常 // 使用类的完全限定名称,俗称全名. Sy ...