More Related Content
Similar to signed distance function
Similar to signed distance function (9)
signed distance function
- 1. 培训任务一
I. 前言
此任务的难度会比原来高一些,因为我认为现在的视觉组需要的不是调opencv库的人 或
是 调试员。所以我希望新人可以掌握以下能力:
OpenCV 基本用法:主要集中在:
core.hpp(数据类型 / Mat)
highgui.hpp(窗口生成)
imgproc.hpp(图形绘制)
Eigen库基本用法
Matrix<Type, row, col> 的相关操作,如norm/dot/cWiseAbs等等
个人认为,这个任务可以帮助新人接触一些有一定数学性的代码,对之后的研发工作有
好处。
线性代数(向量操作为主)
多种情况的考虑,逻辑需要很完备(之后会提到)
II. 预备知识
DF(Distance Field)距离场 / SDF (Signed Distance Field) 有向距离场
可以说,SDF/DF(Distance Field 距离场)的理解与理解灯条优化算法有非常多的联
系之处。灯条模型实际上就是一个线段的距离场(虽然我以前也不知道这个概念)。
2.1 Distance Field
灯条模型V4版本就是线段距离场的变体(使用sigmoid对DF进行了非线性变换)。空间
中一个点到一个 线段(注意不是直线,所以有端点效应)的最短距离,形成一个场。空间
中每一个点都有这样一个值。如下图所示:
- 2. Figure 1. 线段DF示意图
生成这个图片的代码非常简单:
import matplotlib.pyplot as plt
import numpy as np
def distanceField(sp, ep):
brx, bry = ep + np.array([25, 25])
direct = (ep - sp).astype(np.float64)
direct /= np.linalg.norm(direct)
result = np.zeros((bry, brx))
for i in range(bry):
for j in range(brx):
s2p = (np.array([j, i]) - sp).astype(np.float64)
e2p = (np.array([j, i]) - ep).astype(np.float64)
over_e = (e2p.dot(direct) >= 0)
over_s = (s2p.dot(direct) <= 0)
positive = (s2p.dot(normal) > 0)
dist = 0.0
if (over_e == False and over_s == False):
dist = np.sqrt(np.linalg.norm(s2p) ** 2 -
(direct.dot(s2p)) ** 2)
elif (over_e == True):
dist = np.linalg.norm(e2p)
else:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- 3. 具体就不细说了,看Python代码很好懂。做的就是求最小距离的事情。
2.2 Signed Distance Field
很多时候,单纯的DF还满足不了要求。有的时候,我们需要判定一个点是否在一个封闭
图形的 内外,或者是,一个点是否在某段有向曲线 / 折线的其中一边,DF是没有内外 / 方向
信息的。一个非常简单的例子就是:单位圆的SDF数学表达式:
上式可以得到,在圆的内部,SDF值为负,外部SDF值为正。边界上为0。那么对于线段
而言,其SDF可以通过对2.1中代码的简单修改得到,结果如下图:
dist = np.linalg.norm(s2p)
result[i, j] = dist
return result
def visualization(sp, ep, result):
img = np.zeros_like(result)
plt.imshow(result, cmap = 'inferno')
plt.plot([sp[0], ep[0]], [sp[1], ep[1]], c = 'w')
plt.colorbar()
plt.show()
if __name__ == "__main__":
sp = np.array([25, 18])
ep = np.array([100, 88])
res = distanceField(sp, ep)
visualization(sp, ep, res)
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
- 4. Figure 2. 线段SDF示意图
依赖库 作用
OpenCV 4 不要再用OpenCV3了 一律换4
Eigen (libeigen3-dev) ROS自带,矩阵计算
OpenMP(可选) SDF是适合并行的
请读者思考一下,为什么会出现不连续的点?(猜一下实现)。
III. 任务要求
3.1 依赖
3.2 任务具体目标
使用上述库实现 折线端的SDF。折线段在此处定义为:
- 6. Figure 3. 线段以及方向定义
首线段(头部无限延伸) 尾线段(尾部无限延伸)
方向(正负号) * 点到折线段的 最小距离(也就是要找一个距离最近的线段或者点求
距离)。参考Figure 1.跑道形状,特别注意连接处的样子。
特别注意,首尾两端需要特殊处理:由于Figure 2展示了,线段SDF会产生正负号跳
变导致不连续,故首尾两条线段只需要求取 射线的SDF即可,即在某一方向无限延
伸:
首线段:向着线段反方向无限延伸的射线SDF
尾线段:向着线段正方向无线延伸的射线SDF
中间线段:正常,跑道形状的有限SDF
3.2.3 绘制SDF
OpenCV三通道绘制,正负号使用不同的颜色,而颜色的intensity(值大小)对应了距
离。