首先看一下星瞳科技的巡线方案(附上其开源源码):

THRESHOLD = (5, 70, -23, 15, -57, 0) # Grayscale threshold for dark things...
import sensor, image, time
from pyb import LED
import car
from pid import PID
rho_pid = PID(p=0.4, i=0)
theta_pid = PID(p=0.001, i=0)LED(1).on()
LED(2).on()
LED(3).on()sensor.reset()
sensor.set_vflip(True)
sensor.set_hmirror(True)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQQVGA) # 80x60 (4,800 pixels) - O(N^2) max = 2,3040,000.
#sensor.set_windowing([0,20,80,40])
sensor.skip_frames(time = 2000)     # WARNING: If you use QQVGA it may take seconds
clock = time.clock()                # to process a frame sometimes.while(True):clock.tick()img = sensor.snapshot().binary([THRESHOLD])line = img.get_regression([(100,100)], robust = True)if (line):rho_err = abs(line.rho())-img.width()/2if line.theta()>90:theta_err = line.theta()-180else:theta_err = line.theta()img.draw_line(line.line(), color = 127)print(rho_err,line.magnitude(),rho_err)if line.magnitude()>8:#if -40<b_err<40 and -30<t_err<30:rho_output = rho_pid.get_pid(rho_err,1)theta_output = theta_pid.get_pid(theta_err,1)output = rho_output+theta_outputcar.run(50+output, 50-output)else:car.run(0,0)else:car.run(50,-50)pass#print(clock.fps())

直接从主函数看起:

img = sensor.snapshot().binary([THRESHOLD])

先是这样一行代码 ,星瞳科技对此函数的解释是:

根据像素是否在阈值列表 thresholds 中的阈值内,将图像中的所有像素设置为黑色或白色。

这样就可以理解为将图像按目标颜色和非目标颜色二值化为黑白两色,如果巡线的目标以及背景不是黑白两色,即可以采用这样的方法。

然后是很关键的:

line = img.get_regression([(100,100)], robust = True)

我们首先关注其thresholds参数,以下为星瞳科技的注解:

必须是元组列表。 [(lo, hi), (lo, hi), ..., (lo, hi)] 定义你想追踪的颜色范围。 对于灰度图像,每个元组需要包含两个值 - 最小灰度值和最大灰度值。 仅考虑落在这些阈值之间的像素区域。 对于RGB565图像,每个元组需要有六个值(l_lo,l_hi,a_lo,a_hi,b_lo,b_hi) - 分别是LAB L,A和B通道的最小值和最大值。 为方便使用,此功能将自动修复交换的最小值和最大值。 此外,如果元组大于六个值,则忽略其余值。相反,如果元组太短,则假定其余阈值处于最大范围。

并且将

robust = True

即 使用Theil-Sen线性回归算法。

接下来就可以利用得到 两个值 theta以及rho

星瞳科技在此处利用的是霍夫变换:

在直角坐标系上有一点B BB,经过这个点有一条直线,ρ \rho为原点到该直线的距离,垂足是点A ,这个线段与x轴的夹角为θ \theta。如下图1所示:
————————————————
版权声明:此处为CSDN博主「Jeff-Chow000」的原创文章

此处便不再更深讨论霍夫变换

星瞳科技利用这两个值的方式,让人有点难以理解 以及后面的效果也不太尽人意

于是我做了一些改动(附上源码):

THRESHOLD = (7, 255) # Grayscale threshold for dark things...
import sensor, image, time, math, pyb
from pyb import LED ,UART
import ustructLED(1).on()
LED(2).on()
LED(3).on()sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQQVGA) # 80x60 (4,800 pixels) - O(N^2) max = 2,3040,000.
#sensor.set_windowing([0,20,80,40])
sensor.skip_frames(time = 2000)     # WARNING: If you use QQVGA it may take seconds
clock = time.clock()                # to process a frame sometimes.uart = UART(3,115200)   #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1)theta_err = 0
rho_err = 0
coin = 0
x,y,r = 0,0,0
aa = 0
def sending_data(cx,cy,cw,ch):global uart;#frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];#data = bytearray(frame)data = ustruct.pack("<bbhhhhb",      #格式为俩个字符俩个短整型(2字节)0x2C,                      #帧头10x12,                      #帧头2int(cx), # up sample by 4   #数据1int(cy), # up sample by 4    #数据2int(cw), # up sample by 4    #数据1int(ch), # up sample by 4    #数据20x5B)uart.write(data);   #必须要传入一个字节数组while(True):clock.tick()#img = sensor.snapshot().histeq()    #提高对比度img = sensor.snapshot()img.mean(1)img.erode(1)line = img.get_regression([(0,0)], robust = True, roi = [5,30,70,30])if line and (line.magnitude() >= 2):if(line.theta() > 90):aa = -(line.rho()+40)if(aa<-80):aa=-80else:aa = (line.rho() - 40)*2if(aa>80):aa=80rho_err = aatheta_err =90- line.theta()img.draw_line(line.line(), color = 127)FH = bytearray([0x2C,0x12,int(rho_err),int(theta_err),coin,0,0x5B])uart.write(FH)

首先由于我的目标是黑色的线白色的底,所以我直接采用的灰度图像也没有二值化,因为经过实验发现如果底不是纯白色,直接二值化后会有很多噪点,最后这些噪点可能就会对巡线造成一定影响。而灰度图像有0-255个像素值,目标为0那么其他偏黑的像素点也不会算作为目标点但是直接二值化为黑白图像那么一些偏黑的像素点可能就会成为黑点成为噪点。

并且我还限定了roi减少了镜头周围由于光线问题所带来的影响

还利用了一些限制条件:

if line and (line.magnitude() >= 2);

line.magnitude()为得到直线的模长,这个可以根据需要调整

根据霍夫变换得到的line.rho()不能够直接用作error来使用,因为他是一个“ 区域线性值 ”:

当line.theta() > 90时(左侧):

当 line.theta() > 90 && line.theta() < 135 时:

line.rho()从一个负数(大概为-40)变化到0;

当 line.theta() > 135 && line.theta() < 180 时:

line.rho()从0变化为一个正数(大概为40);

也就是说在 line.theta() =90 这条线的左侧,这个区域内,line.rho()的值其实是线性的,但是却不是同号:

那我们可不可以把左侧变成同一个符号的线性值且在 line.theta() = 90 时为0呢?

于是:

if(line.theta() > 90):
            aa = -(line.rho()+40)
            if(aa<-80):
                aa=-80

经过多次测试, line.theta() = 90(左趋近90)时,line.rho() = -40,于是我们将零点右移(line.rho()+40);

这样左边就是从0一直线性变化为一个正数,我们再整体取反,就在 line.theta() > 90 && line.theta() < 180 这个范围内让 line.rho()从0到一个负数的线性变化。

当line.theta() < 90时(右侧):

当line.theta() = 90(右趋近) 时 line.rho() 这是又会变成 一个趋近40的数 且 在 line.theta() 向 0 变化这个过程中line.rho()不断线性的增长。

为了让 line.theta() 又趋近 90时的 line.rho() 值趋于零,同时保证线性性质,我们将右侧 line.rho()整体  减去 40,经过观察左侧与右侧相差一个二倍关系,所以我们将右侧再乘以2。

else:
            aa = (line.rho() - 40)*2
            if(aa>80):
                aa=80

当然,左右两侧都有对应的限幅。

最后得到的 aa 值再赋值给变量 rho_err,即使由于限制条件我们没有更新得到 aa 值,串口传出去的值 rho_err 仍然保持上一次的误差值。

以上就是我根据星瞳科技openmv所改进的巡线方案。

根据星瞳科技openmv巡线小车所改进的巡线方案相关推荐

  1. openmv 神经网络 超出内存_星瞳科技OpenMV视频教程22-神经网络cifar_10

    视频第一部分:https://www.zhihu.com/video/1021334023171338240 视频第二部分:https://www.zhihu.com/video/1021334038 ...

  2. 星瞳科技 OpenMV 的使用

    2019 电子设计大赛 激光炮题目 写的程序 依赖: usart_all.h usart_all.c 见 STM32超级通用串口程序(秘籍) 调用场景: 淘晶驰串口屏 代码: camera.h : # ...

  3. 基于STM32F103智能巡线小车

    ​ 项目描述: 巡线小车是我作为新手入手的第一个项目,基本巡线功能是使用红外传感器循迹模块判断黑线的路径来确定转向方向,同时控制单片机配置PWM占空比波控制小车前进的L298N电机模块,实现前后退,左 ...

  4. 【观察】星环科技:走向融合数据云新时代,背后必有强大数据底座

    毫无疑问,今天国家对数字经济给予了前所未有的高度重视.近期国家就正式印发了<"十四五"数字经济发展规划>,明确将继续坚持推进数字产业化和产业数字化,赋能传统产业转型升级 ...

  5. 星环科技的“星图解密”:只有偏执狂,才能让中国基础软件打破对国外进口的依赖...

    "[报名]数据猿年度精彩活动推荐:访谈调研+企业盘点+榜奖峰会,与数据猿共筑2021 大数据产业创新服务媒体 --聚焦数据 · 改变商业 孙元浩是个<三体>迷. 在<三体& ...

  6. OpenMV:14巡线小车

    文章目录 追小球的小车 巡线小车 这个例子展示了在OpenMV Cam上使用get_regression()方法获得ROI的线性回归.使用这种方法,可以轻松让机器人跟踪所有指向相同大致方向的线. 本例 ...

  7. Arduino案例实操 -- 智能巡防小车(三)图形化巡线小车编程

    巡防小车的巡线功能同时可以用图形化编程软件来实现.博主这里用的图形化编程软件是KRobot. 三.图形化巡线小车编程 3.1 编程环境配置 3.1.1 下载编程软件 3.1.2 安装编程软件 3.2 ...

  8. Arduino案例实操 -- 智能巡防小车(三)Arduino IDE巡线小车编程

    三.Arduino IDE巡线小车编程 3.1 Arduino开发环境 下载免安装ZIP包 下载IDE安装包 3.2 Arduino IDE 3.3 Blink项目实例 打开内置案例 进行程序上传 3 ...

  9. 基于STC89C52RC模块的巡线小车

    基于STC89C52RC模块的巡线小车 在STC89C52RC的基础上使用电机驱动使小车完成巡线,停站,避障,掉头等多功能智能小车 所需头文件: #include <reg52.h> #i ...

最新文章

  1. 重磅推出:AutoProject Studio 自动化项目生成器
  2. Unable to load the Wrapper's native library because none of the following files及解决方法
  3. 关注!部分高校公布暑假时间,暑假将弹性调整?
  4. C语言课后习题(50)
  5. 【开发者portal在线开发插件系列三】字符串 及 可变长度字符串
  6. 如何让我们的VMware虚拟机上网——转载
  7. oracle中查找锁定状态的用户
  8. Android 贝塞尔曲线
  9. 中国信通院发布《区块链赋能新型智慧城市白皮书(2019年)》解读(附全文下载)
  10. 电容或电感的电压_磁场对于电感路径检测的影响
  11. ios识别人脸自动拍照_GitHub - qingweiiOS/FaceRecognition: 活体人脸识别,识别人脸,识别张嘴和摇头动作,并拍照...
  12. intel和ATT汇编格式区别
  13. 看山不是山看水不是水
  14. 立方体在三维坐标中的旋转(3D,Spining)
  15. idea项目打包和部署
  16. im4java+GraphicsMagick 的问题
  17. 什么是响应式布局?原理是什么?
  18. iOS开发如何生成标准的二维码图片
  19. Ordinal numeral
  20. 鼠标移动div效果:鼠标拖曳效果

热门文章

  1. mysql日志文件开启及详解:General_log 和 Binlog
  2. 【财富空间】小心!传统企业即将卷土重来!
  3. 奇安信应急响应-Linux
  4. 麒麟系统开机出现死机,找不到可用打印机处理方法
  5. 计算机常用涵数有哪些,计算机常用函数.doc
  6. Controler方法的返回值可以是什么类型
  7. 关于ElementUI的el-popover的问题:文本换行、修改样式
  8. 开课吧python爬虫数据分析统计服_使用爬虫分析Python岗位招聘情况
  9. DevExpress 22.1.3 源代码版本-2022
  10. android invoke 参数,android 使用反射獲取MediaPlayer的Invoke方法