分享

openmv中用最小二乘法拟合轨迹实现代码分析.1

 云深无际 2021-11-03
在openmv中有一个巡线的功能,在我刨根问底以后发现是一段C++的函数完成的这个功能,看完源码准备写Python的实现。

这个是第一个找到的关键词

我们整体思路还是按照关键字来找

这里是在源码中搜索到的所有的关于线性回归的东西

我们还是先看第一个demo吧,主要是导入的三个库,最重要的是这个image这个库,怎么说呢,承担了大部分的算法任务

这个地方也可以看到是img的方法

这个地方是我们在Openmv里面调用的地方

可以找到的是一份头文件,在里面是统计学的实现

这个是我们关心的函数

我加了一下注释,我们先去看看实现

刚刚看头,现在看实现

但是又没有函数,emmmm奇怪

我们进去看看有什么,看到了核函数

真正的实现在这里

可以看到几千行的代码就是写了几个算法

先看最上面,就是一些版权信息.我大哥教育我给别人的代码的时候一定要写上自己的版权,但是不要留自己的联系方式.这个文件就是实现一下数学上面的一些统计功能.下面有一个是结构体,我们开始看这个代码.

先看代码的小地图,他有这么多~

大概三百多行的程序,首先就是函数签名,已经写好了

一开始就是这两句,第一个是一个结果的布尔变量,一开始认为是关闭的

因为我C++不熟悉,这些函数我只能就看就查.可以看到是申请了一个find这个变量大小的内存空间,随便一找就找到了

第一个是line,不清不楚的一个东西,继续找    

在正式的进入分析之前,我们在看一下这个函数的概览

这个地方的翻译很奇怪

百度也是


可以这样翻译吧?就是说这个地方不是感兴趣的区域,所以直接把ram的内容清空?

对不起,我滑错地方了emmmm

这个地方我们就认为打开这个开关了,下面进行了公式计算的所有的变量


具体也应该就是这个函数了,先不看

->这个符号是指针的指向运算符,通常与结构体一起使用。


#include<stdio.h>struct stu // 定义一个结构体{ char name[10]; // 姓名 int num; // 学号 int age; // 年龄};void main(){ struct stu *s; // 定义一个结构体指针 char str[]="ZhangLi"; s->name = str; // 对结构体中的成员变量name进行赋值 s->num = 2015120; // 对结构体中的成员变量num进行赋值 s->age = 18; // 对结构体中的成员变量age进行赋值}

image.get_regression(

thresholds,invert=False,

roi,

x_stride=2, 

y_stride=1,

area_threshold=10,

pixels_threshold=10,

robust=False)

函数返回回归后的线段对象line,有x1(), y1(), x2(), y2(), length(), theta(), rho(), magnitude()参数。

x1 y1 x2 y2分别代表线段的两个顶点坐标,length是线段长度,theta是线段的角度。magnitude表示线性回归的效果,它是(0,+∞)范围内的一个数字,0代表一个圆。如果场景线性回归的越好,这个值越大。

对图像所有阈值像素进行线性回归计算。这一计算通过最小二乘法进行,通常速度较快,但不能处理任何异常值。

若 robust 为True,则使用Theil-Sen线性回归算法,它计算图像中所有阈值像素的斜率的中位数。若在阈值处理后有太多像素,即使在80x60的图像上,这个O(N^2)操作也可能将您的FPS降到5帧以下。但是,只要阈值转换后的像素数量较少,即使在高达30%的阈值像素是异常值的情况下也依然有效,鲁棒性好。

    thresholds 是元组列表。

[(lo, hi), (lo, hi), ..., (lo, hi)] 定义你想追踪的颜色范围.对于灰度图像,每个元组需要包含两个值 - 最小灰度值和最大灰度值.仅考虑落在这些阈值之间的像素区域. 对于RGB565图像,每个元组需要有六个值(l_lo,l_hi,a_lo,a_hi,b_lo,b_hi) - 分别是LAB通道的最小值和最大值,如果元组大于六个值,则忽略其余值。相反,如果元组太短则假定其余阈值处于最大范围。

    invert 反转阈值操作,像素在已知颜色范围之外进行匹配,而非在已知颜色范围内。

    roi 是感兴趣区域的矩形元组(x,y,w,h)。如果未指定,ROI即整个图像的图像矩形。操作范围仅限于 roi 区域内的像素。

    x_stride 是调用函数时要跳过的x像素数。

    y_stride 是调用函数时要跳过的y像素数。

    如果回归后的边界框区域小于 area_threshold ,则返回None。

    如果回归后的像素数小于 pixel_threshold ,则返回None。

整个代码,我们可以分为5部分其实:

  1. 一开始是进行代码的初始段,进行内存的申请,变量的创建

  2. 然后去自动来判断传进来的img是什么类型的,需要去转换

  3. 注意的一点是需要传入二值化的图像

  4. 接着就是看这个鲁棒性的参数

  5. 假的话,直接最小二乘法,但是要求图像很干净

  6. 真的话,会用Theil-Sen线性回归算法,它计算图像中所有阈值像素的斜率的中位数。

即使是开了第二个算法也还是要进行算法的处理

这个是我们处理的一些注意的事项

开始正式的看,是一个for循环.下面是要不停执行的代码

这个是一个可迭代的函数,其实这些函数是通用的数据结构


我怕C++和其他的语言不一样,就看了看语法

看这个地方,开始对传入的图像要进行处理了.现在来看图像的种类

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多