@iStarLee
2020-02-25T22:31:40.000000Z
字数 9214
阅读 2300
Optimization
前言:最近在整理项目资料,其中有一个三维点云地面部分的提取。关于其理论,在此做一个整理。
假设我们有:三个点,现在需要对这个三个点拟合一条直线。
设这条直线的方程为 。我们希望这条直线可以同时通过这三个点,也就是这条直线的参数要满足:
这里如何假如出口基。入口基的概念?
为了方便我们接下来的理解,现在将其拆分成下面这种形式:
这里更高级一点的说法是,在以为基向量(3维)所张成的2维子空间上,寻找最接近向量的向量。
把视作基向量,画图理解。
![1](Peek 2020-02-21 21-33.gif)
由这个图可知,公式(4)肯定是不成立的,因为向量(红色)就不在基向量所张成的二维平面(二维子空间)里。
所以,我们在这里退而求其次,在该二维子空间中找一个向量(由基向量组成),来代替向量,但是这个向量距离到向量的距离最短(如下图所示)
![2](Peek 2020-02-21 22-04.gif)
如图所示,,显而易见,是向此二维平面的正交投影,此时和之间的距离最近,距离差值维的长度。
而此时,就是我们需要求出的值。
更进一步的理解。当有n组数据带入时,A矩阵的维度将会是n×2.那么这里整个最小二乘拟合问题就可以理解成:是n维线性空间中的两个线性无关的向量,在span{}所张成的子空间中(2维)找到在其中的正交投影,二者之间的距离即是最小二乘优化的最小值min。在基上的投影,即是要求解的变量值,
如果需要拟合的变量不止2个,假设有m个,那么整个问题就可以理解成是n维向量到m维超平面的正交投影求解。
回到公式(3)中来,对其的求解,有以下方法。
其算法理论基于论文:Zermas, D., Izzat, I., & Papanikolopoulos, N. (2017). Fast segmentation of 3D point clouds: A paradigm on LiDAR data for autonomous vehicle applications. Proceedings - IEEE International Conference on Robotics and Automation, 5067–5073. https://doi.org/10.1109/ICRA.2017.7989591
此方法来自论文。
对靠近地面的的n个点,计算其协方差矩阵。对协方差矩阵进行SVD分解,可以得到对应的特征值和特征向量。其中,最小特征值对应的特征向量就是地面平面的法向量。
求证:平面Ax+By+Cz+D=0的法向量为(A,B,C).
证明:假设是当前平面上的两个点。
则有:,,所以两式相减,可得:
,即
右边的矩阵表示平面上的任一点,且该式对平面上的任意两点都成立。所以即是所在平面的法向量。
取n个地面点,计算这n个点的协方差矩阵,然后对其做SVD分解,得到其在各个分量。最小奇异值所对应的向量便是地面的法向量.
由前面的证明可知:
此时的值已知。
此时,均值因为是n个点的均值,默认是最靠近地面所在平面的点。其他所有的n个点,都可以认为更偏离所拟合的平面。即:
\velodyne_points
中所有的topic进行筛选地面点的过程中,所有的点带入式(3)所得到的值符合以下约束: 此方法类似于二维平面的直线拟合。
假设我们有个()靠近地面的点,现假设地面平面所在的方程为。利用这个点对该平面方程的参数进行拟合。原理与二维平面的直线拟合类似,这里不做过多推导。
带入个点的坐标,可得:
即可化为以下的齐次方程组形式(超定方程)。
问题:这种方法如何处理的尺度问题?
下面以这种更普遍的表达形式进行推导。
当是一个超定方程的时候,此等式无解,因此需要取最小二乘的形式,即:
假设世界中的某点(世界坐标未知)被连续n帧相机数据观测到,像素坐标分别是.n帧对应的相机坐标,皆已知。根据三角化,我们可以构建最小二乘表达式,综合帧观测数据,获得点的位置。
预备推导:
:在第帧相机坐标系下的坐标。
其中,是深度值,是像素坐标
展开成矩阵的形式:
我的尼玛的!当然能化成Dy=0的形式。因为这是齐次方程组啊!这里左右都由x,是能单独提出来的。跟Ax=b带一个常数的形式是不一样的!傻逼!
即:
注意D的维度是2×4,P是4×1,此时只是一组数据。所以当有n帧图像数据的时候,D的维度是2n×4.
接下来对D进行SVD分解
SVD的计算方法:https://byjiang.com/2017/11/18/SVD/
对于奇异值,它跟我们特征分解中的特征值类似,在奇异值矩阵中也是按照从大到小排列,而且奇异值的减少特别的快,在很多情况下,前10%甚至1%的奇异值的和就占了全部的奇异值之和的99%以上的比例。
也就是说,我们也可以用最大的k个的奇异值和对应的左右奇异向量来近似描述矩阵。
也就是说:
由于这个重要的性质,SVD可以用于PCA降维,来做数据压缩和去噪。
Mat image = imread("/home/alex/Pictures/earth.jpg", 0);
Mat temp(image.size(), CV_32FC1, Scalar(0));
image.convertTo(image, CV_32FC1);
Mat U, W, V;
SVD::compute(image, W, U, V,4);//opencv得到的V已经经过转置了
Mat w(image.rows, image.cols, CV_32FC1, Scalar(0));
int k = 90;
float radio = (float)(1920 * 1080) / (float)(k*(1920 + 1080 + 1));//1920k 1080k k 分别是 U的行数乘保留的列数 + k个特征值 +V的列数乘k行
for (int i = 0; i < k; i++)
w.ptr<float>(i)[i] = W.ptr<float>(i)[0];
cout << "U = " << U.cols << " U = " << U.rows << endl;
cout << "w = " << w.cols << " w = " << w.rows << endl;
cout << "V = " << V.cols << " V = " << V.rows << endl;
temp = U*w*V;
image.convertTo(image, CV_8UC1);
temp.convertTo(temp, CV_8UC1);
namedWindow("src",WINDOW_NORMAL);
namedWindow("res",WINDOW_NORMAL);
imshow("src",image);
imshow("res",temp);
waitKey(0);
cout << "k = " << k << ",\t" << "radio = " << radio << endl;
输出:
rows: 1920 cols:1080
U = 1920 U = 1920
w = 1080 w = 1920
V = 1080 V = 1080
k = 90, radio = 7.67744
对比如下:
原图:
PCA降维处理:
由此可以总结出:若一个像素为1字节, 原始图像需 字节的存储空间, 而使用SVD分解后只需 字节的存储空间, 以此达到压缩图像(矩阵)的目的.(k即是要保留的前k个最大的特征值)