机器视觉-曲线拟合(直线部分) Curve Fitting

目录

曲线拟合 Curve Fitting

在上一篇文章中,我们讨论了图像的边缘检测,但是边缘检测完毕后存在一个问题就是噪点多,或者换句话说不光滑。

所以我们再增加一个步骤来使得图像轮廓更加平滑:曲线拟合。

原始图像–>(通过边缘检测)得到边缘图像–>(通过轮廓探测contour detector)得到坐标值(几何描述)

在进行正式的拟合之前,我们先回顾一下二维几何知识:向量

向量

向量知识中有个很重要的概念:点积。点积的意义主要是表征向量的相似性。值越大代表相似性越好。

  1. 定义:$\langle\vec{p}, \vec{q}\rangle=p_{1} q_{1}+p_{2} q_{2}$ 其中p=(p1,p2), q=(q1,q2)
  2. 双线性:$\langle\alpha \vec{p}+\beta \vec{r}, \gamma \vec{q}+\delta \vec{s}\rangle=\alpha \gamma\langle\vec{p}, \vec{q}\rangle+\alpha \delta\langle\vec{p}, \vec{s}\rangle+\beta \gamma\langle\vec{r}, \vec{q}\rangle+\beta \delta\langle\vec{r}, \vec{s}\rangle$
  3. 几何定义:$\langle\vec{p}, \vec{q}\rangle=|\vec{p}| \cdot|\vec{q}| \cdot \cos \angle(\vec{p}, \vec{q})$
  4. 拓展:

$\langle\vec{p}, \vec{p}\rangle=|\vec{p}|^{2}$, $\langle\vec{p}, \vec{q}\rangle=0 \quad$ if $\vec{p} \perp \vec{q}$

  • 线和线段

我们可以把任意向量$\vec{x}$表示为$\vec{p}-\vec{q}$的某一段,我们用$\tau$表示比例,即$\tau(\vec{p}-\vec{q})$, $\tau \in[0,1]$

那么我们可以得到$\vec{x}=\vec{p}+\tau(\vec{p}-\vec{q})$

化简得到:

$\vec{x}=(1-\tau) \vec{p}+\tau \vec{q}, \quad \tau \in[0,1]$

同理:$\vec{l}$也可通过以上表达:$\vec{l}=(1-\tau) \vec{p}+\tau \vec{q}, \quad \tau \in[0,1]$

$\vec{l}-\vec{r}=d代表的向量$

$<\vec{l}-\vec{r},\vec{p}-\vec{q}>=0$ 说明d和直线垂直

  • 直线的一般形式:

    $|\vec{n}|=1,\langle\vec{n}, \vec{q}-\vec{p}\rangle=0$ ,$|\vec{n}|为单位向量$

    $\langle\vec{n}, \vec{x}\rangle=\langle\vec{n},(1-\tau) \vec{p}+\tau \vec{q}\rangle=\langle\vec{n}, \vec{p}\rangle+\tau\langle\vec{n}, \vec{q}-\vec{p}\rangle=\langle\vec{n}, \vec{p}\rangle$

    $\begin{aligned} 0 &=\langle\vec{n}, \vec{x}\rangle-\langle\vec{n}, \vec{p}\rangle \ &=\langle\vec{n}, \vec{x}\rangle+c \quad \text { (normal form) } \end{aligned}$

  • 点到直线的距离d:

    \[d=|| \vec{l}-\vec{r} \|=|\langle\vec{n}, \vec{r}\rangle+c|\]

用单位向量表示一般向量:

$\vec{v}=\left(\begin{array}{l}v_{1} \ v_{2}\end{array}\right)$

$\vec{n}=\frac{1}{|\vec{v}|}\left(\begin{array}{c}-v_{2} \ v_{1}\end{array}\right)$

$\rightarrow \quad|\vec{n}|=1, \vec{n} \perp \vec{v}$

每个向量都可以用极坐标来表示:

\[\vec{v}=r \cdot\left(\begin{array}{c}\cos \phi \\ \sin \phi\end{array}\right) \quad,r \geq 0, \phi \in[0,2 \pi)\] \[\phi=\operatorname{atan}_{2}\left(v_{1}, v_{2}\right)\]

通过点积可以来判断一个多边形是否面向摄像机(游戏开发中重要的一点);根据点积来计算光照效果(聚光);在计算机图学中进行方向性的判断

霍夫转换 Hough Transform

在边缘检测完毕后,我们通过霍夫转换,可以在边缘位图(edge bitmaps)中找到边缘线,每条线可以通过下面的式子来代替:

$x \cdot \cos \phi+y \cdot \sin \phi+c=0$

with $0^{\circ} \leq \phi<180^{\circ}$ and $c \in \mathbb{R}$

为什么可以这么表示呢?

因为在一般笛卡尔坐标系的直线表达式中,如y = kx+b,存在斜率为无穷大的情况,我们想办法找到一个类似于极坐标的表达方式。通过以上公式表达的方式我们称之为参数空间。在笛卡尔坐标系中的直线表达和 参数空间内的直线表达可以理解为一种映射,可以理解为同一种物体的不同维度的观察。

我们知道图中直线和它的垂线(虚线),一旦直线位置确定,那么其垂线的位置也是确定的。反之亦然。

如何找到这种映射关系呢?

假设有三个点A,B,C我们要判断其是否共线,这里我们假设其共线。

img

这条线的方程为

\[y=-x+2\]

围绕A点可以做无数条直线,B、C同理。那么如果说其中的某三条线重合了,说明ABC共线。

那么这三条线的极坐标表示也是一样的,在参数空间内就相交于一点。

那么围绕A点扫描的所有直线的表达式为:

\[f=0 \times \sin \theta+2 \times \cos \theta, \theta \in[0, \pi]\]

围绕B点扫描的所有直线表达式为:

\[f=2 \times \sin \theta+0 \times \cos \theta, \theta \in[0, \pi]\]

围绕C点扫描的所有直线表达式为:

\[f=4 \times \sin \theta-2 \times \cos \theta, \theta \in[0, \pi]\]

然后做出函数图像,我们发现,三个函数交于

\[\left(\frac{\pi}{4}, \sqrt{2}\right)\]

我们现在知道了,他们相交的直线是以辐角为45°,幅值为$\sqrt{2}$的直线,大家再看笛卡尔坐标系中的直线位置,就明白了其映射关系。大家可以使用其他值作为例子进行体会。

img

霍夫转换的基本步骤

  1. 根据边缘线在参考空间中计算或者画出正弦曲线
  2. 计算交点

值得注意的是,在现实图像处理中,交点并不唯一。(多条线混合在一起)

所以我们只能在高密度的区域中进行找点:

  1. 使用离散累加器单元阵列;
  2. 对每个单元计算正弦曲线穿过的数量;
  3. 在累加器阵列中进行局部最大值处理(根据线的参数)

有点类似我们小时候画三角形的垂直平分线,画完后交不到一点,我们用铅笔继续涂黑。

在许多边缘上的许多边缘点的霍夫变换

  1. 用0初始化具有足够精度的累加器阵列
  2. 使得所有满足线方程的累加器单元增加计数(有点拗口,就是计数)
  3. 在累加器中找到局部最大值(图像中最主要的参数)

在找到线参数后,可以将离线距离小的边缘像素分配到边缘线上。

但需要做两个工作:1. 确定线的起点和终点。2. 确定允许最大尺寸的间隙。

霍夫变换的性质

  1. 结果取决于累积器数组的大小和精度
  2. 在实践中,确定累积器阵列中的重要峰值可能是困难的
  3. 梯度方向被忽略
  4. 累加器数组在”自然场景“中溢出(我猜是计算量过大)

img

上图是一张经过霍夫变换后的图,在图中我们可以知道,圆弧部分并没有找到。

边缘追踪 Edge following

鉴于霍夫变换的缺点,我们可以通过另一条路线:

边缘检测edge detection–>边缘追踪edge following–>线段分割polyline segmentation–>直线拟合 line fitting

边缘追踪大体思路

  1. 边缘检测器产生具有边缘像素的位图
  2. 收集所有边缘像素并按拓扑顺序链接它们
  3. 使用梯度信息(如果可用)进行链接
  4. 结果:描述轮廓线的边缘像素列表

img

直线分割 Polyline Segmentation

边缘跟踪产生了有序的像素列表,但这些像素列表并不会主动或者自动的生成连线用以表示轮廓,所以我们的任务就是:细分像列表,使子列表可以用线段表示。

这里有很多的算法,我们只考虑Ramer Douglas Peucker算法,道格拉斯-普克算法

道格拉斯-普克算法的基本思路

在最远的顶点进行递归细分折线

  1. 从第一个点到最后一个点连成线
  2. 计算各像素到线的距离
  3. 若最大的距离大于容差(自己定义的),则在最远的顶点打破边缘列表,并将算法再次应用到两个子列表(列表被打破成两个)

总体思想就是递归思想。

直线拟合

由于折线分割和霍夫转换的结果不一定是最优的,所以我们提出直线拟合的算法。

很容易想到我们以前中学学过的直线拟合算法:最小二乘法

最小二乘法

在这里我们做一下基本的回顾和加深:

在前面的二维几何知识回顾里,我们知道了:

如果给定了我们单位向量$\vec{n}$以及$c$, 我们可以计算$\overrightarrow{x_{i}}$到直线的距离为

\[d_{i}=\left|\left\langle\vec{n}, \vec{x}_{i}\right\rangle+c\right|\]

我们找到最小的$d_{i}$

不想看推到过程的可以跳到后面,看结论就行了。

完全最小二乘法:

\[\underset{\vec{n}, c}{\operatorname{minimise}} \sum_{i=1}^{N} d_{i}^{2}\] \[\text { subject to }\langle\vec{n}, \vec{n}\rangle=1\]

拉格朗日算子(自行回顾高等数学)

\[\mathcal{L}(\vec{n}, c, \lambda)=\sum_{i=1}^{N} d_{i}^{2}-\lambda(\langle\vec{n}, \vec{n}\rangle-1)\] \[=\sum_{i=1}^{N}\left(\left\langle\vec{n}, \vec{x}_{i}\right\rangle+c\right)^{2}-\lambda(\langle\vec{n}, \vec{n}\rangle-1)\]

对$c$进行归零偏导

\[\frac{\partial \mathcal{L}}{\partial c}=2 \sum_{i=1}^{N}\left\langle\vec{n}, \vec{x}_{i}\right\rangle+2 N c \stackrel{!}{=} 0\] \[\rightarrow c=-\frac{1}{N} \sum_{i=1}^{N}\left\langle\vec{n}, \vec{x}_{i}\right\rangle=-\frac{1}{N}\left\langle\vec{n}, \sum_{i=1}^{N} \vec{x}_{i}\right\rangle=-\left\langle\vec{n}, \frac{1}{N} \sum_{i=1}^{N} \vec{x}_{i}\right\rangle\]

对$n_{1}$和$n_{2}$归零偏导

\[\frac{\partial \mathcal{L}}{\partial n_{1}}=2\left(\sum_{i} x_{i, 1}^{2}\right) n_{1}+2\left(\sum_{i} x_{i, 1} x_{i, 2}\right) n_{2}+2\left(\sum_{i} x_{i, 1}\right) c-2 \lambda n_{1} \stackrel{!}{=} 0\] \[\frac{\partial \mathcal{L}}{\partial n_{2}}=2\left(\sum_{i} x_{i, 1} x_{i, 2}\right) n_{1}+2\left(\sum_{i} x_{i, 2}^{2}\right) n_{2}+2\left(\sum_{i} x_{i, 2}\right) c-2 \lambda n_{2} \stackrel{!}{=} 0\]

替换:

\[\underbrace{\left(\sum_{i} x_{i, 1}^{2}-\frac{1}{N}\left(\sum_{i} x_{i, 1}\right)^{2}\right)}_{=: \alpha} n_{1}+\underbrace{\left(\sum_{i} x_{i, 1} x_{i, 2}-\frac{1}{N} \sum_{i} x_{i, 1} \sum_{i} x_{i, 2}\right)}_{=: \beta} n_{2}=\lambda n_{1}\] \[\underbrace{\left(\sum_{i} x_{i, 1} x_{i, 2}-\frac{1}{N} \sum_{i} x_{i, 1} \sum_{i} x_{i, 2}\right)}_{=\beta} n_{1}+\underbrace{\left(\sum_{i} x_{i, 2}^{2}-\frac{1}{N}\left(\sum_{i} x_{i, 2}\right)^{2}\right) n_{2}=\lambda n_{2}}_{=\gamma}\]

用矩阵形式表示:

\[\left(\begin{array}{ll} \alpha & \beta \\ \beta & \gamma \end{array}\right) \vec{n}=\lambda \vec{n}\]

$\lambda$是特征值,$\vec{n}$是特征向量

两种结果:

\[\lambda_{1} \geq \lambda_{2} \geq 0\]

$\lambda_{2}$–>最小距离, $\lambda_{1}$–>最大距离。

最小二乘法的步骤

  1. 从所有的边缘像素中计算: $\sum_{i} x_{i, 1}, \sum_{i} x_{i, 2}, \sum_{i} x_{i, 1}^{2}, \sum_{i} x_{i, 2}^{2}, \sum_{i} x_{i, 1} x_{i, 2}$

  2. 计算矩阵 $\left(\begin{array}{ll}\alpha & \beta \ \beta & \gamma\end{array}\right)$ 的特征向量和特征值,取较小的特征值
  3. 根据$\vec{n}$计算$c$
  4. 如果您对线段感兴趣,请根据投影在线上的边缘像素确定起点和终点。

直线估计

稳健性

稳健性是指在估计过程中,拟合过程中,对模型误差的不敏感性。

在最小二乘法中,如果出现异常值,那么拟合的直线很容易被带偏。

然而异常值在机器视觉中经常出现。

现在有两个思路:

  1. 减少总异常值的影响–> M估计,M Estimator
  2. 忽略异常值–>RANSAC算法

M估计

其中$\rho$越小,越靠近直线。

RANSAC随机抽样一致算法

一种通过使用观测到的数据点来估计数学模型参数的迭代方法

random sample consensus

RANSAC算法是一个学习的技巧,通过使用观测数据的随机样本来估计模型参数。RANSAC使用投票机制来寻找优化的拟合结果。每个数据元被用来投票一或多个模型。投票机制基于两点假设:

(1)噪音大的特征并不能一直单独为某个模型投票

(2)有足够多的特征来拟合一个好的模型

思路

搜索通过尽可能多点靠近的线

算法

  1. 随机选择两点
  2. 拟合
  3. 检查公差带之外的点数(异常值的数量)
  4. 用不同的点重复这个过程
  5. 选择异常值数量最少的线