赞
踩
虽然是第一次参加全国大学生电子设计大赛的新手,但是也是信心满满的完成这次四天三夜的电赛。由于我是负责视觉方面的,所以在此分享一下我做视觉处理的经验。接着就废话少说,看看我的方案吧!
首先,当看到这个题目的时候就感觉这个题目相对来说不是那么的难,但还是有一些坑在里面的。从题目里面就能够分析出我们需要将红色激光点以及A4纸黑色方框识别出来,怎么去识别就成为了接下来讨论的问题了。首先我们开始准备的是Openmv4 Plus这一款,因为这个要比普通款的算力要更加强大,确实到后面普通款实在是跑不掉我的能够代码,所以硬件也应该保证上。
其实激光头识别映射到我们平时的应用当中就是色块识别,就是在图像中去识别设置好的阈值色块。但是在做到基础三的过程当中会遇到当红色激光笔走到黑线框的时候,红色激光被黑色吸收了导致阈值识别不到。这时有的人说可以用设置为灰度图像,调节亮度啥的。但是最后我还是参考的另一个博主的方法就是用曝光度来调节一个阈值,再带入到色块的阈值里。实在不行就在摄像头上再加上一个滤光片,这样也有一定的效果。
- import sensor, image, time
-
- sensor.reset()
- sensor.set_pixformat(sensor.RGB565)
- sensor.set_framesize(sensor.QVGA)
- sensor.skip_frames(time = 2000)
- # 您必须关闭自动增益控制和自动白平衡,否则他们将更改图像增益以撤消您放置的任何曝光设置
- sensor.set_auto_gain(False)
- sensor.set_auto_whitebal(False)
- sensor.set_auto_exposure(False, 2000) #调节曝光度
-
- clock = time.clock()
-
- while(True):
- clock.tick()
- img = sensor.snapshot()
- print(clock.fps())

接着将调节好的阈值带入到寻找色块的代码当中,注意在用find_blobs()函数时要将area_threshold这个色块面积大小的参数调小一点大概在2~6左右。因为我们开始在调的过程当中就是把这个参数调到了15就导致了那个色块一直在抖,只要把这个色块面积调小一点就解决了。
img.find_blobs(red_td_01, roi=ROI_TH, pixels_threshold=2, area_threshold=5, merge=True, invert=0)
其实识别黑色方框也不是很难的问题,直接使用OPENMV官方库的寻找矩形函数find_rects()。
通过四天三夜的比赛以及赛后的总结分析后,我在看来重点难点有以下几个方面:
- # 在图像中寻找红色激光笔 多阈值的寻找红色激光点
- light_01 = img.find_blobs(red_td_01, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
- light_02 = img.find_blobs(red_td_02, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
- light_03 = img.find_blobs(red_td_03, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
还有黑色矩形框的识别,在比赛的过程中发现当矩形框下向左或向右倾斜时它识别的矩形框不一样,有时候是外框,有时候是内框。并且有时候还会识别错误。所以在识别时应该加入前50次的总数判断,这样能够提高识别率。
接下共享部分代码:
- uart = pyb.UART(3, 115200) # 串口3初始化,波特率115200
- uart.init(115200, bits=8, parity=None, stop=1) # 8位数据位,无校验位,1位停止位
- RIO = (92, 42, 180, 175) #外框
-
- def return_zuobiao(x, y): # 矫正相对坐标的函数
- x = (x - 92)
- y = -(y - 42)
- return x, y
-
- def find_mode(nums): # 求解列表中的众数
- if nums is not None:
- num_count = {0:0}
- for num in nums:
- if num in num_count:
- num_count[num] += 1
- else:
- num_count[num] = 1
-
- mode = max(num_count, key=num_count.get)
-
- return mode
-
- def find_max(blobs): # 寻找范围内的最大色块
- max_size=0
- for blob in blobs:
- if blob.pixels() > max_size:
- max_blob = blob
- max_size = blob.pixels()
- return max_blob
-
-
- while(True):
- clock.tick()
- img = sensor.snapshot().lens_corr(strength = 1.8 , zoom = 1.0)
- img.draw_rectangle(RIO, color=(255, 0, 0), scale=4)
- #img.draw_rectangle(ROI_TH, color=(0, 255, 0), scale=4)
- # -----矩形框部分-----
- # 在图像中寻找矩形
- if (flag<50): # 在外框内寻找矩形框
- for r in img.find_rects(roi= RIO,threshold = 5000):
- # 判断矩形边长是否符合要求
- # 判断矩形框大于45度时
- if r.w() > 90 and r.h() > 90 and r.w() < 150 and r.h() < 150:
- # 在屏幕上框出矩形
- img.draw_rectangle(r.rect(), color = (255, 0, 0), scale = 2)
- # 获取矩形角点位置
- corner = r.corners()
- # 标记出矩形框四个角的位置
- img.draw_circle(corner[0][0], corner[0][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[1][0], corner[1][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[2][0], corner[2][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[3][0], corner[3][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
-
-
- if r.w() < 90 and r.h() < 90:
- # 在屏幕上框出矩形
- img.draw_rectangle(r.rect(), color = (255, 0, 0), scale = 2)
- # 获取矩形角点位置
- corner = r.corners()
- # 在屏幕上圈出矩形角点
- img.draw_circle(corner[0][0], corner[0][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[1][0], corner[1][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[2][0], corner[2][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
- img.draw_circle(corner[3][0], corner[3][1], 2, color = (0, 0, 255), thickness = 2, fill = False)
-
- # -----激光笔部分-----
- # 在图像中寻找红色激光笔 多阈值的寻找红色激光点
- light_01 = img.find_blobs(red_td_01, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
- light_02 = img.find_blobs(red_td_02, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
- light_03 = img.find_blobs(red_td_03, roi=ROI_TH, pixels_threshold=1, area_threshold=2, merge=True, invert=0)
-
- if light_01:
- light_01_max = find_max(light_01)
- x0, y0 = return_zuobiao(light_01_max[5], light_01_max[6])
- print("黑",x0, y0)
- img.draw_rectangle(light_01_max.rect(), color = (255, 0, 0), scale = 2)
-
- elif light_02:
- light_02_max = find_max(light_02)
- x0, y0 = return_zuobiao(light_02_max[5], light_02_max[6])
- img.draw_rectangle(light_02_max.rect(), color = (0, 255, 0), scale = 2)
- print("偏暗",x0, y0)
-
- elif light_03:
- light_03_max = find_max(light_03)
- x0, y0 = return_zuobiao(light_03_max[5], light_03_max[6])
- img.draw_rectangle(light_03_max.rect(), color = (0, 0, 255), scale = 2)
- print("偏亮",x0, y0)
-
-
- # -----寻找众数坐标部分-----
- if (flag == 50):
- x1_mode = find_mode(list_x1)
- x2_mode = find_mode(list_x2)
- x3_mode = find_mode(list_x3)
- x4_mode = find_mode(list_x4)
- y1_mode = find_mode(list_y1)
- y2_mode = find_mode(list_y2)
- y3_mode = find_mode(list_y3)
- y4_mode = find_mode(list_y4)
- magnitude_mode = find_mode(list_magnitude)
- flag+=1
- else:
- send_data_packet(x0, y0, # 串口发送
- x1_mode, y1_mode,
- x2_mode, y2_mode,
- x3_mode, y3_mode,
- x4_mode, y4_mode)

作为第一次参加电赛的人来说,拿到省一这个成绩也相当不错了,就是不知道后面能不能进国赛了。其实开始我们队在第二天的时候就将基础部做的差不多了,第三天就开始在调后面的了,但是确实有点没有想全面导致我们的效果不太好,结果第四天都还在完善。但是最后结果还算是好的。由于我们是第一次打电赛,所以我们的经验还是欠缺一些浪费了很多时间,以及在一些小细节方面还做的不是很好。但是未来还有机会做的更好。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。