最近好多要电赛题的源码,其他csdn营销号下载都需要会员或钱,正好最近课设又要做一遍电赛小车题,哥们先把代码开源了,饿死营销号
电赛宝藏链接:
四天三夜,那布满着未知与紧迫感的气息让荷尔蒙无比兴奋,挑战着脑力与体力的极限!
2021全国大学生电子设计竞赛F题参赛简记
2021年小车题完整代码及教程!
2021电赛F题视觉教程+代码免费开源
其他年份的经典题目的源码都在这里啦!
【电赛源码合集】19电磁炮.zip、17板球.zip、15风力摆.zip、13倒立摆.zip、全国大学生电子设计竞赛历年真题(1994-2021).zip
参加电赛必看的经验贴!
全国电子设计竞赛指导 (老学长挥泪经验之谈)
论文模板及评分标准!
全国大学生电子设计竞赛论文写作模板及评分标准
正文开始咯:
视觉的一个任务是视觉上位机模块识别数字并进行滤波和判断处理,传指令给下位机;另一个任务是红线循迹。
不多bb,先上代码和效果图~
链接:百度网盘——小车主板pcb文件
提取码:3n50
–来自百度网盘超级会员V3的分享
README:蓝牙连接后,发送字符 " t " 给小车进入测试程序
K210数字识别效果:(我媛哥的手真好看)

openmv红线循迹效果:

小车整体图:


硬件工具:K210、openmv
软件工具:Maixpy IDE、OpenMV IDE
IDE可到官网下载:
https://www.sipeed.com/index.html
文章目录
正常操作是上位机是识别,给下位机传数据,处理放到下位机;假如你有个坑比队友,处理还是放上位机干吧;
经过算法优化,现在几乎不存在掉帧。

1、在小车行驶过程中,会存在数字不能完全进入视野中情况等存在有很多帧误识情况,要进行滤噪处理
2、每一帧要做处理的同时每个目标值的矩形框进行处理,每个目标值的矩形框还要进行滤波
3、在上位机上不断的优化算法,减少掉帧
4、在Maixpy IDE中python 的numpy、pandas巴拉巴拉包都调不了
5、图中最多出现四个,但这里设了读六个矩形框,留两个容错,不然有误识别的直接死机
6、给下位机传送指令:
一开始初始化识别传送对应的数字
若为12,则后面不在传送指令
若为34,则后面路口处传"l"or"r"
若为5678,则后面两个路口传送两次"l"or“r”
7、设计思路
通过初始化函数识别一开始给入的数字并保存下来;
根据识别的情况进入不同的程序;
12号病房,识别完了以后是不用在路上在识别的,直接关掉程序;
34号病房,初始化识别完了,加两秒延迟,避免在开始的时候连续识别传指令,要在路上识别一次,要保证返回来的时候不识别不然又给下位机传指令了,还要保证初始化识别完了以后不会紧接着识别误认为是路上的标签给下位机传指令;
5678也一样,但是路上得识别两次穿两次指令;
训练集:

测试集:

训练输出结果:

将通过拍摄3403张赛道数字照片,使用labellmg进行标签标定,制作数据集,yolov5训练
(哥们和队友从晚上十点标到凌晨两点(哭脸))
详细过程可看下面文章:
注意:这里yolov5得到的是.pt文件,需要进行模型转换,转化成可以加载在K210板上的.kmodel模型(后面细讲)
https://www.sipeed.com/index.html
官方教程:
https://wiki.sipeed.com/soft/maixpy/zh/get_started/upgrade_maixpy_firmware.html
更新固件库:

文件目录:

将上述文件全复制到tf卡中,tf卡插入k210
注意:tf卡先格式成FAT32格式,部分牌子的tf卡格式了也不能挂载到k210上,建议多换几张卡试试
IDE中运行效果:

引脚9是TX,引脚10是RX,波特率为115200
通过usb转ttl连接到电脑上
初始识别数字为6,两次转向是向左

第一版本:
import sensor,image,lcd,time
import KPU as kpu
from machine import UART
from fpioa_manager import fm
lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(0)
sensor.run(1)
#加载yolov5模型
task = kpu.load("/sd/yolov5.kmodel")
f=open("anchors.txt","r")
anchor_txt=f.read()
L=[]
for i in anchor_txt.split(","):
L.append(float(i))
anchor=tuple(L)
f.close()
f=open("lable.txt","r")
lable_txt=f.read()
lable = lable_txt.split(",")
f.close()
#设置RX、RT引脚
fm.register(9, fm.fpioa.UART1_TX, force=True)
fm.register(10, fm.fpioa.UART1_RX, force=True)
#设置串口通信
uart_A = UART(UART.UART1, 115200, 8, 1, 0, timeout=1000, read_buf_len=4096)
anchor = (0.1766, 0.1793, 0.4409, 0.3797, 0.6773, 0.5954, 1.0218, 0.9527, 2.158, 1.6841)
sensor.set_windowing((224, 224))
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
classes=["9","1","4","2","3","8","5","6","7" ]
#全局变量,保存初始化识别的数字
intnum = 0
#初始化识别函数
def begin(intnum):
TF = 1
#得分序列,放1-8识别的次数,每一帧识别成哪个,对应的位置加一,1-8哪个先到10即最终识别为哪个
List_score01 = [0]*8
while(TF):
img = sensor.snapshot()
#code是yolov5返回的每个矩形框的参数
#例图中出现两个目标区域的时候:[{"x":9, "y":99, "w":55, "h":82, "value":0.697979, "classid":8, "index":0, "objnum":2}, {"x":137, "y":105, "w":56, "h":67, "value":0.939132, "classid":4, "index":1, "objnum":2}]
code = kpu.run_yolo2(task, img)
#print(code)
if code:
for i in code:
#画目标区域矩形框
a = img.draw_rectangle(i.rect())
a = lcd. display(img)
list1=list(i.rect())
#print(classes[i.classid()])
#识别到的加1
List_score01[int(classes[i.classid()])-1] += 1
#print(List_score01)
if(List_score01[0] >= 10):
intnum = 1
#给下位机通信传指令
uart_A.write('1')
#print(1)
#退出初始化循环
TF = 0
if(List_score01[1] >= 10):
intnum = 2
uart_A.write('2')
#print(2)
TF = 0
if(List_score01[2] >= 10):
intnum = 3
uart_A.write('3')
#print(3)
TF = 0
if(List_score01[3] >= 10):
intnum = 4
uart_A.write('4')
#print(4)
TF = 0
if(List_score01[4] >= 10):
intnum = 5
uart_A.write('5')
#print(5)
TF = 0
if(List_score01[5] >= 10):
intnum = 6
uart_A.write('6')
#print(6)
TF = 0
if(List_score01[6] >= 10):
intnum = 7
uart_A.write('7')
#print(7)
TF = 0
if(List_score01[7] >= 10):
intnum = 8
uart_A.write('8')
print(8)
TF = 0
else:
a = lcd.display(img)
return intnum
#34道路识别函数
def threefour(intnum):
#设置二维矩阵,存放每一个矩形框中不同数字识别的次数
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
TF = 1
while(TF):
#加载一帧图像
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
int_i = 0
for i in code:
int_i +=1
a=img.draw_rectangle(i.rect())
a = lcd. display(img)
list1=list(i.rect())
b=(list1[0]+list1[2])/2
#对应的矩阵值加一
List_score02[int_i][int(classes[i.classid()])-1] += 1
print(List_score02[int_i])
#该目标框逐个数字分析是否出现次数到达10,即为该目标区域中的数字
for ii in range(8):
if(List_score02[int_i][ii] >= 10):
intnum02[int_i] = ii+1
#该目标区域中的数字是否是初始化识别的数字
if(intnum == intnum02[int_i]):
#判断位置,从而判断先做向右转
if(b < 75):
uart_A.write("l")
print("l")
TF = 0
if(b > 75):
uart_A.write("r")
print("r")
TF = 0
else:
a = lcd.display(img)
return 0
#5678道路识别函数
def fivesixseveneight(intnum):
#设置二维矩阵,存放每一个矩形框中不同数字识别的次数,一帧中最多有四个目标区域,但这里设置六个,防止有误识别的造成有很多矩形框程序暴死
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
TF = 2
#5678道路识别要识别两次,传两次指令,两次直接通过延时函数断开
while(TF):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
int_i = 0
for i in code:
int_i +=1
a=img.draw_rectangle(i.rect())
a = lcd. display(img)
list1=list(i.rect())
b=(list1[0]+list1[2])/2
List_score02[int_i][int(classes[i.classid()]) -1] += 1
print(List_score02[int_i])
for ii in range(8):
if(List_score02[int_i][ii] >= 10):
intnum02[int_i] = ii+1
if(intnum == intnum02[int_i]):
if(b < 75):
uart_A.write("l")
print("l")
TF -= 1
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
time.sleep(3)
if(b > 75):
uart_A.write("r")
print("r")
TF -= 1
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
time.sleep(3)
else:
a = lcd.display(img)
return 0
#执行程序
intnum = begin(intnum)
time.sleep(3)
if(intnum == 3 or intnum == 4):
threefour(intnum)
if(intnum == 5 or intnum == 6 or intnum ==7 or intnum == 8):
fivesixseveneight(intnum)
uart_A.deinit()
del uart_A
a = kpu.deinit(task)
第二版本:
import sensor,image,lcd,time
import KPU as kpu
from machine import UART
from fpioa_manager import fm
lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(0)
sensor.run(1)
#加载yolov5模型
task = kpu.load("/sd/yolov5.kmodel")
f=open("anchors.txt","r")
anchor_txt=f.read()
L=[]
for i in anchor_txt.split(","):
L.append(float(i))
anchor=tuple(L)
f.close()
f=open("lable.txt","r")
lable_txt=f.read()
lable = lable_txt.split(",")
f.close()
#设置RX、RT引脚
fm.register(9, fm.fpioa.UART1_TX, force=True)
fm.register(10, fm.fpioa.UART1_RX, force=True)
#设置串口通信
uart_A = UART(UART.UART1, 9600, 8, 1, 0, timeout=1000, read_buf_len=4096)
anchor = (0.1766, 0.1793, 0.4409, 0.3797, 0.6773, 0.5954, 1.0218, 0.9527, 2.158, 1.6841)
sensor.set_windowing((224, 224))
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
classes=["9","1","4","2","3","8","5","6","7" ]
#全局变量,保存初始化识别的数字
intnum = 0
#初始化识别函数
def begin(intnum):
TF = 1
#得分序列,放1-8识别的次数,每一帧识别成哪个,对应的位置加一,1-8哪个先到10即最终识别为哪个
List_score01 = [0]*8
while(TF):
img = sensor.snapshot()
#code是yolov5返回的每个矩形框的参数
#例图中出现两个目标区域的时候:[{"x":9, "y":99, "w":55, "h":82, "value":0.697979, "classid":8, "index":0, "objnum":2}, {"x":137, "y":105, "w":56, "h":67, "value":0.939132, "classid":4, "index":1, "objnum":2}]
code = kpu.run_yolo2(task, img)
#print(code)
if code:
for i in code:
#画目标区域矩形框
a = img.draw_rectangle(i.rect())
a = lcd. display(img)
list1=list(i.rect())
#print(classes[i.classid()])
#识别到的加1
List_score01[int(classes[i.classid()])-1] += 1
#print(List_score01)
if(List_score01[0] >= 10):
intnum = 1
#给下位机通信传指令
uart_A.write('A')
print(1)
#退出初始化循环
TF = 0
if(List_score01[1] >= 10):
intnum = 2
uart_A.write('B')
print(2)
TF = 0
if(List_score01[2] >= 10):
intnum = 3
uart_A.write('C')
print(3)
TF = 0
if(List_score01[3] >= 10):
intnum = 4
uart_A.write('D')
print(4)
TF = 0
if(List_score01[4] >= 10):
intnum = 5
uart_A.write('E')
print(5)
TF = 0
if(List_score01[5] >= 10):
intnum = 6
uart_A.write('F')
print(6)
TF = 0
if(List_score01[6] >= 10):
intnum = 7
uart_A.write('G')
#print(7)
TF = 0
if(List_score01[7] >= 10):
intnum = 8
uart_A.write('H')
print(8)
TF = 0
else:
a = lcd.display(img)
return intnum
#道路识别函数
def then(intnum):
while(1):
#设置二维矩阵,存放每一个矩形框中不同数字识别的次数,一帧中最多有四个目标区域,但这里设置六个,防止有误识别的造成有很多矩形框程序暴死
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
TF = 1
while(TF):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
int_i = -1
for i in code:
int_i +=1
a=img.draw_rectangle(i.rect())
a = lcd. display(img)
list1=list(i.rect())
b=(list1[0]+list1[2])/2
List_score02[int_i][int(classes[i.classid()]) -1] += 1
#print(int_i)
print(str(List_score02[int_i]) + str(int_i))
for ii in range(8):
#int_i是第几个框,ii是第几个框中的每个数字
if(List_score02[int_i][ii] == 10 and intnum == ii+1):
if(b < 75):
uart_A.write("L")
print("L")
TF = 0
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
if(b > 75):
uart_A.write("R")
print("R")
TF = 0
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
else:
a = lcd.display(img)
TF = 0
List_score02 = [[0]*8] * 6
intnum02 = [0]*6
return 0
#执行程序
time.sleep(3)
uart_A.write("E")
intnum = begin(intnum)
time.sleep(3)
then(intnum)
uart_A.deinit()
del uart_A
a = kpu.deinit(task)
openmv就是玩具
——某位老哥(收录名人名言)
用openmv红线循迹,这部分比较简单,就不多说了吧
循迹测试:

测试结果:

虽然2021电赛过去了,但是现在回味起来依然很香~

如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur
前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源
嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主