赞
踩
省赛:由于这个比赛是两年一届,并未做足充分的准备,但是通过一定的单片机基础,加上速成能力,也就是熬夜学,通过疯狂的网络搜索,在省赛第5 入选国赛
下面来简单介绍一下我们作品:
主控:因为识别如果你不将图像处理放到主控上处理,就有点麻烦,因为我们是使用的K210作为识别装置的,识别速度很快,如果进行识别发串口,就有点赌,本来速度就快,处理都处理不过来,当然你也可以用个取平均的算法,貌似这样也不是很好,还是得把识别和分类放到一起,这样处理才连贯。
最开始考虑的使用openmv,或者opencv在树莓派上做图像识别。 这个方案现阶段真不建议尝试,说实话,效果很不好。先不说准确率了,光是识别帧率就低到离谱。 所以当时也很巧合,发现一款很不错,上手很简单的开发板。就是Sipeed科技推出的几款k210芯片的开发板,第一眼看到,真是精致,再了解它的功能,简直强大,再看它的价格,wc,好划算(虽然这一年涨价了,还涨了不少)。尤其是这么小巧的一个板子,跑图像识别真是强,还很流畅,为什么呢?自己去看吧。
原文链接:https://blog.csdn.net/GUA8122HOU/article/details/120317568
这是k210总代码:
- #2023 10 15 派大星改
- # object classifier boot.py
- # generated by maixhub.com
- from fpioa_manager import *
- from modules import ultrasonic
- from fpioa_manager import fm
- from Maix import GPIO
- import math
- import struct
- import sensor, image, lcd, time
- import KPU as kpu
- import gc, sys
- from Maix import GPIO
- from machine import UART
- from machine import Timer,PWM
- #
- #
- i= 8
- # 定义超声波传感器的触发引脚和回响引脚
- trig_pin = 0
- echo_pin = 1
-
- #控制串口通信
- board_info_tx=15
- board_info_rx=17
- # 将GPIO口初始化为输入/输出模式
- fm.register(trig_pin, fm.fpioa.GPIO0)
- fm.register(echo_pin, fm.fpioa.GPIO1)
- trig = GPIO(GPIO.GPIO0, GPIO.OUT)
- echo = GPIO(GPIO.GPIO1, GPIO.IN)
- tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_PWM) #控制2个云台舵机
- S1 = PWM(tim, freq=50, duty=0, pin=21)
- tim = Timer(Timer.TIMER1, Timer.CHANNEL0, mode=Timer.MODE_PWM)
- S2 = PWM(tim, freq=50, duty=0, pin=23)
-
- value = 0xFF
- s = struct.pack('B', value)
- list_of_values = [255]*3
- s = struct.pack('3B', *list_of_values) #串口通信结束符
-
- fm.register(board_info_tx,fm.fpioa.UART1_TX,force=True)
- fm.register(board_info_rx,fm.fpioa.UART1_RX,force=True)
- uart_A = UART(UART.UART1, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)
- #uart_A = UART(UART.UART1, 115200,read_buf_len=4096)
-
-
- def Servo_1(servo,angle):
- S1.duty((angle+90)/180*10+2.5) #竖直舵机
- def Servo_2(servo,angle):
- S2.duty((angle+90)/270*10+2.5) #水平舵机
- #超声波
- def measure_distance():
- trig.value(0) # 发送触发信号
- time.sleep_ms(2)
- trig.value(1)
- time.sleep_us(10)
- trig.value(0)
- start_time = time.ticks_ms()
- while echo.value() == 0 and time.ticks_diff(time.ticks_ms(), start_time) < 3000:
- pass
-
- # 如果等待超时,返回错误代码 -1
- if time.ticks_diff(time.ticks_ms(), start_time) >= 3000:
- print("Error: no echo received!")
- return -1
-
- # 记录回响信号的时间戳
- t1 = time.ticks_us()
- while echo.value() == 1:
- pass
- t2 = time.ticks_us()
-
- print(t2)
- # 计算距离(单位:厘米)
- duration = t2 - t1
- distance = duration * 0.017
- print(distance)
- if distance < 15: #距离判断
- write_str = ("t20.bco=63488")
- uart_A.write(write_str)
- print("满载")
- uart_A.write(s)
- else:
- write_str = ("t20.bco=34784")
- uart_A.write(write_str)
- print("未满载")
- uart_A.write(s)
- return
-
-
-
-
-
-
- def lcd_show_except(e):
- import uio
- err_str = uio.StringIO()
- sys.print_exception(e, err_str)
- err_str = err_str.getvalue()
- img = image.Image(size=(224,224))
- img.draw_string(0, 10, err_str, scale=1, color=(0xff,0x00,0x00))
- lcd.display(img)
- #开机启动
- ########################################################################################################################
- def main(labels = None, model_addr="/sd/m.kmodel", sensor_window=(224, 224), lcd_rotation=0, sensor_hmirror=False, sensor_vflip=False):
- sensor.reset()
- sensor.set_pixformat(sensor.RGB565)
- sensor.set_framesize(sensor.QVGA)
- sensor.set_windowing(sensor_window)
- sensor.set_hmirror(sensor_hmirror)
- sensor.set_vflip(sensor_vflip)
- sensor.run(1)
-
- lcd.init(type=1,invert=1) #小LCD屏幕
- lcd.rotation(lcd_rotation)
- lcd.clear(lcd.WHITE)
- if not labels:
- with open('labels.txt','r') as f:
- exec(f.read())
- if not labels:
- print("no labels.txt")
- img = image.Image(size=(320, 240))
- img.draw_string(90, 110, "no labels.txt", color=(255, 0, 0), scale=2)
- lcd.display(img)
- return 1
- try:
- img = image.Image("startup.jpg")
- lcd.display(img)
- except Exception:
- img = image.Image(size=(320, 240))
- img.draw_string(90, 110, "loading model...", color=(255, 255, 255), scale=2)
- lcd.display(img)
- task = kpu.load(model_addr)
- try:
- ####################################循环######################################################################################
- a= 0
- while(a<3):
- print("启动")
- write_str = ("page main") #跳到计数主屏幕
- uart_A.write(write_str)
- uart_A.write(s)
- print(write_str)
- a+=1
-
-
- while(True):
- Servo_1(S1, i)
- Servo_2(S2, 0)
- time.sleep_ms(500)
- measure_distance() #满载检查
- print("满载jianche ")
- write_str = ("n5.val=0") #初始化串口屏幕
- uart_A.write(write_str)
- uart_A.write(s)
- print(write_str)
- while(True):
-
- img = sensor.snapshot()
- t = time.ticks_ms()
- fmap = kpu.forward(task, img)
- t = time.ticks_ms() - t
- plist=fmap[:]
- pmax=max(plist) #判断最大置信度
- if pmax < 0.4: #检测空物品
- empty_str = "Not subject"
- img.draw_string(0, 0, empty_str, scale=2)
- lcd.display(img)
- Servo_1(S1, i)
- Servo_2(S2, 0)
- break
- max_index=plist.index(pmax)
- img.draw_string(0,0, "%.2f : %s" %(pmax, labels[max_index].strip()), scale=2)
- img.draw_string(0, 200, "t:%dms" %(t), scale=2)
- lcd.display(img)
-
-
- if plist.index(pmax)==0 or plist.index(pmax)==6: #fruit "vegetable" 厨余垃圾
- if pmax >= 0.5:
-
- time.sleep_ms(50) #等待垃圾掉落待静止的时间
- Servo_2(S2,90)
- time.sleep_ms(1000)
- Servo_1(S1,-20)
- time.sleep_ms(1500)
- #write_str = ()
- Servo_1(S1,i)
- time.sleep_ms(400)
- Servo_2(S2,0)
- time.sleep_ms(1000)
- uart_A.write("t7.txt=\"厨余垃圾\"")
- print("厨余垃圾ok")
- uart_A.write(s)
-
- time.sleep_ms(450) #舵机归位
- Servo_1(S1,i)
- time.sleep_ms(450)
- break
- #time.sleep_ms(500) #等待垃圾掉落待静止的时间
-
- if plist.index(pmax)== 1 or plist.index(pmax)==2 or plist.index(pmax)== 7: #capsule 有害垃圾
- if pmax >= 0.6: #0.5
-
- time.sleep_ms(50) #时隔几秒后继续检测垃圾
- #Servo_2(S2,90)
- #time.sleep_ms(500)
- Servo_1(S1,-30)
- time.sleep_ms(1500)
- #write_str = ()
- uart_A.write("t7.txt=\"有害垃圾\"")
- print("有害垃圾ok")
- uart_A.write(s)
-
- time.sleep_ms(450) #舵机归位
- Servo_1(S1,i)
- Servo_2(S2,0)
- time.sleep_ms(450)
- break
-
-
-
- if plist.index(pmax)==4 or plist.index(pmax)==8: #bottle 可回收垃圾
- if pmax >= 0.5:
-
- time.sleep_ms(50) #等待垃圾掉落待静止的时间
- Servo_2(S2,180)
- time.sleep_ms(1000)
- Servo_1(S1,-20)
- time.sleep_ms(1500)
- #write_str = ()
- Servo_1(S1,i)
- time.sleep_ms(400)
- Servo_2(S2,0)
- time.sleep_ms(1000)
- uart_A.write("t7.txt=\"可回收垃圾\"")
- print("可回收垃圾ok")
- uart_A.write(s)
- time.sleep_ms(1200) #舵机归位
- break
-
-
-
- if plist.index(pmax)==3 or plist.index(pmax)== 5 or plist.index(pmax)== 9: #cigarette 其他垃圾
- if pmax >= 0.7: #0.5
-
- time.sleep_ms(50) #等待垃圾掉落待静止的时间
- Servo_2(S2,-90)
- time.sleep_ms(1000)
- Servo_1(S1,-20)
- time.sleep_ms(1500)
- #write_str = ()
- Servo_1(S1,i)
- time.sleep_ms(400)
- Servo_2(S2,0)
- time.sleep_ms(1000)
-
- uart_A.write("t7.txt=\"其他垃圾\"")
- print("其他垃圾ok")
- uart_A.write(s)
- time.sleep_ms(450) #舵机归位
- Servo_1(S1,i)
- Servo_2(S2,0)
- time.sleep_ms(500)
- break
- uart.deinit() # uart.deinit()和kpu.deinit(task)用于关闭UART和释放模型资源。
- del uart
- except Exception as e:
- raise e
- finally:
- if not task is None:
- kpu.deinit(task)
-
- if __name__ == "__main__":
- try :
- #labels = ["bottle", "brick", "capsule", "pill", "stone", "vegetable"]
- #labels = ["chuyu", "dainci", "jiaolang", "shitou", "shuiping", "taoci", "yaobaozhung", "yilaguan"]
- labels = ["chuyu", "dainci", "jiaolang", "shitou", "shuiping", "taoci", "xiaotudou", "yaobaozhung", "yilaguan", "zhuangtou"]
- main(labels=labels, model_addr="/sd/m.kmodel")
- except Exception as e:
- sys.print_exception(e)
- lcd_show_except(e)
- finally:
- gc.collect()
-

识别:K210,虽然这东西是挺强的,但是模型有点难训练。我们是根据maixpy 官网的本地环境来进行训练的,环境有点麻烦,也可以直接CPU跑 但是有点发烫 我电脑都跑坏了,修了我300大洋,所以还是使用GPU跑,训练速度也快、
分类装置:初赛直接就是云台加舵机,没啥讲的,k210控制就可以了
满载检测:超声波检查,省赛的时候就做了一个,因为超声波挺费时间的,比赛一个物体识别的时间是有要求的,我们做了一个,结果没用上,没抽到,国赛我把其他三个加上去,结果是我自己选一个,气死,开始我还用小车的红外避障模块来做,简单的一批,后面还是觉得测的不如超声波准。还是用的
- import time
- from fpioa_manager import fm
- from Maix import GPIO
-
- # 定义超声波传感器的触发引脚和回响引脚
- trig_pin = 0
- echo_pin = 1
-
- # 将GPIO口初始化为输入/输出模式
- fm.register(trig_pin, fm.fpioa.GPIO0)
- fm.register(echo_pin, fm.fpioa.GPIO1)
- trig = GPIO(GPIO.GPIO0, GPIO.OUT)
- echo = GPIO(GPIO.GPIO1, GPIO.IN)
-
-
- def measure_distance():
- # 发送触发信号
- trig.value(0)
- time.sleep_ms(2)
- trig.value(1)
- time.sleep_us(10)
- trig.value(0)
-
- # 等待回响信号
- while echo.value() == 0:
- pass
- t1 = time.ticks_us()
-
- while echo.value() == 1:
- pass
- t2 = time.ticks_us()
-
- # 计算距离(单位:厘米)
- duration = t2 - t1
- distance = duration * 0.034 / 2
- return distance
-
-
- while True:
- distance = measure_distance()
- print("Distance: %.2f cm" % distance)
- time.sleep(1)

屏幕:直接使用串口屏,简单的要si,不要十分复杂的代码,你会发串口就可以用。
压缩:我们使用的是电动推杆,用arduino uno 控制 通过监听串口判断是不是可回收垃圾,然后启动
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。