8

结构光相移法-多频外差原理+实践(上篇)

 3 years ago
source link: https://mp.weixin.qq.com/s/dhdzMibdAUU0zp77TS81NQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

640?wx_fmt=jpeg

01 相移法原理
02 双频外差原理
03 多频率外差原理
04 代码实践

01 相移法原理

结构光法原理其实是跟双目视觉一样的,都是要确定对应“匹配点”,利用“视差”三角关系计算距离,所不同的是:
  • 双目视觉通过“被动”匹配唯一特征点
  • 相移法作为结构光法中的一种,通过主动投影多副相移图案来标记唯一位置。

说明:虽然大多数结构光系统是单目的,但我们可以将其“双目”的,因为投影仪可以看做是一个“逆向”的相机,明白了这点,对于结构光系统一些公式推导就容易很多。

对于“双目”系统来说,最重要的工作是通过唯一标记来标记某一点,假设我们只投射一个周期的数据,我们从投影仪投出去的光栅公式如下:

640?wx_fmt=png

640?wx_fmt=png
比如说四步相移公式:
640?wx_fmt=png
我们主要关心的是求解出相位主值,因为它对每个像素点是唯一的,假设我们从相机中获取了这四副图像,那怎么反过来求解相位主值?

需要说明的是,虽然这个公式对整副相移图像的,但是这公式对每个像素都是独立的,所以即使我们拿从相机拍摄到经过调制变形的图像来求解,依然可以得到单个像素点唯一的相位主值。

联立4个方程,得到:
640?wx_fmt=png
  • 拍摄到什么图像
我们要得到某个像素点的唯一“标记”,也就是这个相位主值,代回这个公式即可,都可以得到唯一值。得到了唯一值,建立匹配关系,就可以利用三角公式进行重建。
640?wx_fmt=png
640?wx_fmt=png
其中:横坐标为任意一行的像素,这张图中使用周期为11的像素条纹作为正弦光栅。

02 双频外差原理

解决的方法有很多,分为空域和时域展开两种:
  • 空域展开:依靠空间相邻像素点之间的相位值恢复绝对相位,如果重建表面不连续,则出现解码错误。
  • 时域展开:将每个像素点的相位值进行独立计算,有格雷码和多频外差两种,其中格雷码方法对物理表面问题敏感,并且多投影的图并不能用来提升精度,多频外差精度更高。
当然目前还有更多精度更高、效率更快的相位展开方法,在这里暂时不予讨论,这里主要讨论多频外差原理。

多频外差原理:通过多个不同频率(周期)正弦光栅的相位做差,将小周期的相位主值转化为大周期的相位差,从而使得相位差信号覆盖整个视场,然后再根据相位差来得到整副图像的绝对相位分布。

这里以双频外差为例,原理如图1所示:
640?wx_fmt=png
640?wx_fmt=png

注:通常我们说的相位函数的周期,代表的是一个周期正弦函数所占的像素单位个数。

03 多频率外差原理

640?wx_fmt=png

640?wx_fmt=png

其可以完成整个视场的无歧义标记。

04 代码实践

640?wx_fmt=png
依据相移法得到的包裹相位图如下图所示,不同颜色代表不同频率的相位主值:
640?wx_fmt=png
我们进行叠加后的效果:
640?wx_fmt=png

在这里,我们可以看到,由两个周期小的相位可以合成一个周期更大的编码图案。

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

明白了原理,我们来代码实践一下,需要注意的是,求解出来的相位我们要进行归一化到区间操作
import numpy as npimport matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号def phase_simulation(WIDTH, T1, T2, T3):    pha1, pha2, pha3 = np.zeros(shape=WIDTH), np.zeros(shape=WIDTH), np.zeros(shape=WIDTH)    t1, t2, t3 = 1, 1, 1    for idx in range(WIDTH):        if t1 > T1: t1 = 1  # 重置一下        pha1[idx] = (t1 / T1) * 2 * np.pi        if t2 > T2: t2 = 1        pha2[idx] = (t2 / T2) * 2 * np.pi        if t3 > T3: t3 = 1        pha3[idx] = (t3 / T3) * 2 * np.pi        t1 += 1; t2 += 1; t3 += 1    return pha1, pha2, pha3def parse_phase(pha1, pha2, T1, T2):    pha12 = np.zeros_like(pha1)    # 计算Delta(如果满足条件,输出左侧,否则右侧)    pha12 = np.where(pha1 >= pha2, pha1 - pha2, pha1 - pha2 + 2 * np.pi)    # # 跟下面这段代码等价    # for idx in range(0, pha12.shape[0]):    #     if pha1[idx] >= pha2[idx]:    #         pha12[idx] = pha1[idx] - pha2[idx]    #     else:    #         pha12[idx] = pha1[idx] - pha2[idx] + 2 * np.pi    T12 = T1 * T2 / (T2 - T1)    # 方法1    pha12 = T2 / (T2 - T1) * pha12    # # 方法2    # m = np.round((T2 / (T2 - T1) * pha12 - pha1) / (2 * np.pi))    # pha12 = 2 * np.pi * m + pha12    # 归一化到[0,2π]    min_value, max_value = np.min(pha12), np.max(pha12)    pha12 = (pha12 - min_value) * (2 * np.pi / (max_value - min_value))    return pha12, T12if __name__ == '__main__':    # 视场宽度    WIDTH = 854    # 条纹周期    T1 = 11    T2 = 12    T3 = 13    pha1, pha2, pha3 = phase_simulation(WIDTH, T1, T2, T3)    X = np.arange(0, WIDTH)    plt.plot(X, pha1, label="pha1")    plt.plot(X, pha2, label="pha2:")    plt.plot(X, pha3, label="pha3")    plt.title("相移主值图(仿真)")    plt.xlabel("像素")    plt.ylabel("w/rad")    plt.legend()    plt.show()    # 解相位    pha12, T12 = parse_phase(pha1, pha2, T1, T2)    pha23, T23 = parse_phase(pha2, pha3, T2, T3)    pha123, T123 = parse_phase(pha12, pha23, T12, T23)    plt.plot(X, pha12, label="pha12")    plt.plot(X, pha23, label="pha23")    plt.plot(X, pha123, label="pha123")    plt.title("解出绝对相位")    plt.xlabel("像素")    plt.ylabel("w/rad")    plt.legend()    plt.show()
640?wx_fmt=png
640?wx_fmt=png
可以看出,最终解出的绝对相位线单调递增,每个相位值时唯一的,虽然在一些交界处会有些许误差。结构光多频外差的原理很简单,而精度这块,其实很大程度依赖于标定、高反处理这些地方。这一期内容将分为上下两期,为了便于理解,不再讲述更多内容,更多我们下一期再讲!怎么拿实际投影拍摄到的光栅图片来还原绝对相位!备注:作者也是我们「3D视觉从入门到精通」特邀嘉宾:一个超干货的3D视觉学习社区本文仅做学术分享,如有侵权,请联系删文。下载1在「3D视觉工坊」公众号后台回复:3D视觉即可下载 3D视觉相关资料干货,涉及相机标定、三维重建、立体视觉、SLAM、深度学习、点云后处理、多视图几何等方向。下载2在「3D视觉工坊」公众号后台回复:3D视觉github资源汇总即可下载包括结构光、标定源码、缺陷检测源码、深度估计与深度补全源码、点云处理相关源码、立体匹配源码、单目、双目3D检测、基于点云的3D检测、6D姿态估计源码汇总等。下载3在「3D视觉工坊」公众号后台回复:相机标定即可下载独家相机标定学习课件与视频网址;后台回复:立体匹配即可下载独家立体匹配学习课件与视频网址。

重磅!3DCVer-学术论文写作投稿 交流群已成立

扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、多传感器融合、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流、ORB-SLAM系列源码交流、深度估计等微信群。

一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。

640?wx_fmt=png▲长按加微信群或投稿

640?wx_fmt=jpeg

▲长按关注公众号

3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近2000星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款640?wx_fmt=jpeg 圈里有高质量教程资料、可答疑解惑、助你高效解决问题觉得有用,麻烦给个赞和在看~640?wx_fmt=gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK