文章之前12月發(fā)了一次,但是我后來申請的免畢設(shè)后,用到了一些文字,所以刪了這篇文章,但是還是查重了,于是我把一些程序講解先刪了,等畢設(shè)結(jié)束后再編輯加上。
這次電賽我沒有準(zhǔn)備多少東西,只提前準(zhǔn)備了圖像識別和坐標(biāo)計算一類的。在20年的省賽幫過雪地調(diào)過k210后,自己后來為了比賽,也買了一個。參加了省物聯(lián)網(wǎng)和交通科技比賽。
由于這邊學(xué)校對競賽支持力度不大,經(jīng)費(fèi)不多,所以我就用了一塊k210.用它作識別和巡線其實(shí)是完全夠用的。只需要寫個判斷分開就好。
識別這塊我起初自己配的aconda和pycharm環(huán)境,不過出現(xiàn)各種問題,沒耐下心去做(這學(xué)期課程依舊很多,而且還有別的事)。直接用了mxyolo這款軟件,一鍵配置環(huán)境庫,再加上英偉達(dá)cuda加速就可以了。
我用了總共600張圖片,花了20分鐘大概(我的老筆記本gtx1050,沒有獨(dú)顯直連所以也沒有出過視頻了。)?對象的1650大概在10分鐘出頭。標(biāo)記是門體力活,好在有了不錯的識別效果,圖片樣本拍攝是在不同光線和距離情況下,最終模型識別成功率大概在80%左右,速度很快。只是,7容易識別成1,5有時候會識別成2,這是在距離不定的情況下,我想是訓(xùn)練數(shù)據(jù)集不夠。迭代在30,loss挺低了。
在攝像頭懸空情況下,正好可以識別2-3個數(shù)字。
軟件圖后續(xù)想起來再補(bǔ)吧,我突然想寫文章時候發(fā)現(xiàn)當(dāng)時并沒有截圖。
再說一說軟件部分吧,k210我是在Maixpy下進(jìn)行編寫的,調(diào)用外設(shè)庫非常方便,只是沒有花括號的縮進(jìn),我看著很難受。
初始化程序打開了各個外設(shè)以及定義了灰度值,灰度值需要在菜單欄里的——工具——機(jī)器視覺——閾值編輯器,選擇幀緩沖圖像,拖動滾動條,把紅線與地面的背景分隔開。紅線為白,其它為黑。(麻了,我又沒存圖,當(dāng)時只留意存了十字線和巡線的。)
import sensor,image,lcd,time
import KPU as kpu
from Maix import FPIOA, GPIO
from fpioa_manager import fm
from board import board_info
from machine import UART
from Maix import GPIO
fm.register(17, fm.fpioa.GPIO0, force=True)
s_flag = GPIO(GPIO.GPIO0, GPIO.OUT)
flag=1
GRAYSCALE_THRESHOLD = [(87, 255)] #劃分的灰度值
THRESHOLD =(10, 34, -41, 74, -109, 127) #攝像頭垂直于地面
lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
#sensor.set_hmirror(0) #鏡像
#sensor.set_vflip(1) #翻轉(zhuǎn)
lcd.rotation(2) #旋轉(zhuǎn)方向 參數(shù)是0~3, 分別代表順時針旋轉(zhuǎn) 0度 90度 180度 270度
sensor.set_windowing((224, 224))
#sensor.set_brightness(2)
sensor.run(1)
clock = time.clock()
fm.register(23,fm.fpioa.UART2_TX)
uart_A = UART(UART.UART2, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)
task = kpu.load("/sd/tt.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()
a = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)
f=open("lable.txt","r")
labels_txt=f.read()
labels = labels_txt.split(",")
f.close()
死循環(huán)中我是通過標(biāo)志位來切換兩種模式的。首先上電先進(jìn)入數(shù)字識別,第一次完成后進(jìn)入巡線程序。后續(xù)切換是通過另一個主控發(fā)送數(shù)據(jù)改變的。
主控那邊我簡單說下吧,是通過閉環(huán)加入編碼器計里程和十字線輔助判斷每個路口,自加是第幾個路口,停下來發(fā)信號給k210,在開始數(shù)字判斷。
下面程序是老版本的,少寫一些通信,數(shù)字在屏幕的左右正負(fù)偏差坐標(biāo)即是數(shù)字在病房路口的位置,通過這個信息去PWM差速轉(zhuǎn)向。
使用的PD進(jìn)行轉(zhuǎn)向控制,能精確鎖住中線行駛。主控我認(rèn)為用什么都可以,stc12啊,stc8都可以。之前自己做亞克力小車,加升壓,在智能車賽道上一圈開環(huán)也能跑個16-18秒(沒有加三岔路和圓環(huán))。
這次比賽我用的是GD32的芯片,因?yàn)楸阋?,他們家封裝的庫還是挺好用的。
? ?
?
?這題我選擇后,第一天深夜我才確定用攝像頭方案,以前沒有試過巡線,凌晨3點(diǎn)從openmv那里速成,代碼搬過來了。后續(xù)我想學(xué)學(xué)opencv。
發(fā)現(xiàn)這題坑真多,量很大,光靠我一個人肯定做不完,所以需要點(diǎn)取巧的方法。
開環(huán)直線行駛很穩(wěn)定,但是到十字路口會被干擾,于是我加了判斷,并且把左右兩邊的白色區(qū)域給忽略了,還是當(dāng)作一條直線。(在主控上根據(jù)我經(jīng)過的十字路口和數(shù)字進(jìn)行綜合判斷的)
def c_line():
s_flag.value(1) #識別到數(shù)字后17口高電平s
img = sensor.snapshot().binary([THRESHOLD])
lcd.display(img)
roi0=(80, 0,30, 30) #給識別中線的位置標(biāo)上興趣框,并畫下來,驗(yàn)證。
most_pixels=0
img.draw_rectangle(roi0, color =170)
blob0 = img.find_blobs(GRAYSCALE_THRESHOLD, roi=roi0,pixels_threshold=100, area_threshold=100, merge=True)
if blob0:
for n in range(len(blob0)):
#目標(biāo)區(qū)域找到的顏色塊(線段塊)可能不止一個,找到最大的一個,作為本區(qū)域內(nèi)的目標(biāo)直線
if blob0[n].pixels() > most_pixels:
most_pixels = blob0[n].pixels()
#merged_blobs[i][4]是這個顏色塊的像素總數(shù),如果此顏色塊像素總數(shù)大于
largest_blob = n
R = 1
else:
R = 0
roi1=(80, 200,30, 30)
img.draw_rectangle(roi1, color =170)
blob1 = img.find_blobs(GRAYSCALE_THRESHOLD, roi=roi1,pixels_threshold=100, area_threshold=100, merge=True)
if blob1:
for n in range(len(blob1)):
if blob1[n].pixels() > most_pixels:
most_pixels = blob1[n].pixels()
largest_blob = n
L = 1
else:
L = 0
uart_A.write('L')
uart_A.write(str(L))
uart_A.write('Z')
uart_A.write('R')
uart_A.write(str(R))
uart_A.write('X')
line=img.get_regression([(20, 250)],roi=(0,0,210,210),x_srtide=2,y_srtide=1,robust=False) #灰度 白黑
if(line):
rho_err = abs(line.rho())-img.width()/2 #piancha
#print(int(rho_err))
uart_A.write('P')
uart_A.write(str(int(rho_err)))
uart_A.write('S')
if line.theta()>90:
theta_err = line.theta()-180
else:
theta_err = line.theta()
img.draw_line(line.line(), color = 127)
print('R',R ,'L',L)
#print(rho_err,line.magnitude(),theta_err)
下面部分是識別數(shù)字的,比較簡單,都是框架。因?yàn)楸荣愖约鹤鲎约河玫?,串口沒有用到多嚴(yán)格的格式,只加了頭尾,確保傳的數(shù)正確就好。主控那邊我加了語音播報病房號,也算個額外加分點(diǎn),這個屢試不爽~?
def c_num():
global flag
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
print(anchor)
a = lcd.display(img)
if code:
for i in code:
a=img.draw_rectangle(i.rect(),(0,255,0),2)
a = lcd.display(img)
for i in code:
lcd.draw_string(i.x()+45, i.y()-5, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.GREEN)
#print(labels[i.classid()])
#print('x',i.x(),y,'i.y()')
if(labels[i.classid()]=='1'):
#print('1')
uart_A.write('N')
uart_A.write('1')
uart_A.write('M')
if(labels[i.classid()]==' 2'):
uart_A.write('N')
uart_A.write('2')
uart_A.write('M')
if(labels[i.classid()]==' 3'):
uart_A.write('N')
uart_A.write('3')
uart_A.write('M')
if(labels[i.classid()]==' 4'):
uart_A.write('N')
uart_A.write('4')
uart_A.write('M')
if(labels[i.classid()]==' 5'):
uart_A.write('N')
uart_A.write('5')
uart_A.write('M')
if(labels[i.classid()]==' 6'):
uart_A.write('N')
uart_A.write('6')
uart_A.write('M')
if(labels[i.classid()]==' 7'):
uart_A.write('N')
uart_A.write('7')
uart_A.write('M')
if(labels[i.classid()]==' 8'):
uart_A.write('N')
uart_A.write('8')
uart_A.write('M')
flag=0
s_flag.value(0)
else:
a = lcd.display(img)
#uart_A.write('N')
#uart_A.write('0')
#uart_A.write('M')
Python我并沒有好好學(xué)過,幾乎沒寫過幾次,都是臨時抱佛腳,代碼寫的很爛。?這次沒有什么詳細(xì)講解,代碼直接甩出去,(不負(fù)責(zé)的我,這次寫完就不想補(bǔ)充完善了)留給大家自己慢慢研究了。我感覺除了那個灰度圖像閾值需要自己調(diào)整外,其他沒有什么太大問題。
額,這次比完賽并沒有完賽資料,就沒有參加立創(chuàng)開源,少拿一份獎金,不過問題不大,我懶。
立創(chuàng)的獎金比學(xué)校的還要高,學(xué)校又要降獎金,因?yàn)榻衲昴锚劦?、參賽的人多了,我笑了……這學(xué)校各種惡心人的事,擺爛等我畢業(yè)答辯完再說。真不如我在一個好??拼龊?。
白嫖個便攜式示波器挺好的。
文章來源:http://www.zghlxwxcb.cn/news/detail-470435.html
繼19年電賽在??颇眠^一次國一后,沒想到在本科這邊又拿了一次。唯一一次遺憾的就是智能車了,但那個是外在因素,等完全畢業(yè)之后再談。文章來源地址http://www.zghlxwxcb.cn/news/detail-470435.html
到了這里,關(guān)于2021電賽F題數(shù)字識別和巡線部分的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!