2021电子设计竞赛G题飞控视觉之openmv找起点

wuchangjian2021-11-12 23:46:16编程学习

总览

今年飞控基础部分和发挥部分都需要定点降落,就需要我们对起点进行识别,起点长这样。起点
看到这个图片,我的第一个想法是先找黑色色块,把整体找到,之后再想办法识别中间的部分。但是经过简单的尝试我发现起点的图案由于中间白色十字的分割会被识别成四个黑色色块。再加上我们的场地起点旁边并不是纯白,也会有不少黑色色块,比较杂乱,因此放弃了这个方案。
第二个想法是用找圆的函数。这个想法经验证后可行,接下来详述该方案。

方案详述

openmv提供了找圆的函数,可以直接调用,返回圆心坐标及圆的半径在这里插入图片描述
使用这个函数会产生一些问题,我们一一解决:首先是如果全图不加限制地找圆的话帧率会非常低,并且容易误识别到一些“虚空之圆”,因此我们对要找的圆的半径进行限制,经过测试,在我们的飞机飞行高度为一米五的情况下将圆的半径限制在15到25效果较好,并且使用ROI让找圆不在视野边界处进行,这样帧率较为正常,误识别率较低。

 circles =  img.find_circles(roi = [30,30,260,180],threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10,
            r_min = 15, r_max = 25, r_step = 2)

其次,由于该题中黑色的杆有可能放在起点旁边,如果杆的底盘是黑色圆盘,就会造成误识别,由于起点半径为50cm,正常黑杆的底盘不会比这个大,因此,我们在找到的黑色圆中筛选出最大的一个。

if circles:
        for circle in circles:
            r.append(circle.r())
        p_n = r.index(max(r))

max函数是我自己写的一个返回列表最大值的函数,大家可以很轻松地写一个使用。至此我们解决了当黑杆底盘和起点同时出现在视野中时如何识别的问题。但如果视野中只有黑杆底盘时依旧会误识别,并且经过测试如果视野中既没有起点也没有黑杆底盘,找圆函数也可能返回一些“虚空之圆”。所以我在找到圆的外接方框范围内寻找黑色色块,从而排除“虚空之圆”的干扰,并且在以圆心为中心,以圆的半径为边长的正方形范围内找白色色块,从而排除黑色底盘的干扰。

circle_blobs_black = img.find_blobs([(0, 32, -17, 18, -22, 19)],roi = [circles[p_n].x()-circles[p_n].r(),circles[p_n].y()-circles[p_n].r(),circles[p_n].r()*2,circles[p_n].r()*2])
        circle_blobs_white = img.find_blobs([(45, 82, -25, 8, -14, 5)],roi = [int(circles[p_n].x()-circles[p_n].r()/2),int(circles[p_n].y()-circles[p_n].r()/2),circles[p_n].r(),circles[p_n].r()])
        if circle_blobs_black and circle_blobs_white:
            img.draw_circle(circles[p_n].x(), circles[p_n].y(), circles[p_n].r(), color = (255, 0, 0))
            p_x = circles[p_n].x()
            p_y = circles[p_n].y()
            return p_x,p_y

整个函数就是这样

def find_point(img):
    #img.lens_corr(3.0,0.75)
    r = []
    circles =  img.find_circles(roi = [30,30,260,180],threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10,
            r_min = 15, r_max = 25, r_step = 2)
        #img.draw_circle(c.x(), c.y(), c.r(), color = (255, 0, 0))
    if circles:
        for circle in circles:
            r.append(circle.r())
        p_n = r.index(max(r))
        circle_blobs_black = img.find_blobs([(0, 32, -17, 18, -22, 19)],roi = [circles[p_n].x()-circles[p_n].r(),circles[p_n].y()-circles[p_n].r(),circles[p_n].r()*2,circles[p_n].r()*2])
        circle_blobs_white = img.find_blobs([(45, 82, -25, 8, -14, 5)],roi = [int(circles[p_n].x()-circles[p_n].r()/2),int(circles[p_n].y()-circles[p_n].r()/2),circles[p_n].r(),circles[p_n].r()])
        if circle_blobs_black and circle_blobs_white:
            img.draw_circle(circles[p_n].x(), circles[p_n].y(), circles[p_n].r(), color = (255, 0, 0))
            p_x = circles[p_n].x()
            p_y = circles[p_n].y()
            return p_x,p_y
            print(p_x,p_y)

这样就可以较好地找到起点,第一次写文章,欢迎大家指正。

相关文章

2021-11-15

蒜头君给了一个长度为 NN(不大于 500500)的正整数序...

如何点击回车往记事本里添加一条数据并清空里面的内容

① 用v-model 双向绑定语法 ② 用@keyup.enter=方...

gcc命令

最简单的命令 g​cc test.c -o test gcc shell.c sqlit...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。