三维重建(二):包裹相位以及绝对相位求解

光栅投影

目标:获取包裹相位以及相位的展开

相位法是指分别投射同一频率的多幅光栅图像至物体表面用以获得物体表面信息对应相位,一组图像之间有固定的相位差。目前主要以三步相移,四步相移和五步相移为主。区别在于一组之间的相位差不同,以四步相移为例周期为2pi 所以同一组之间的相位差为(2pi/4 = pi/2)

一:包裹相位的获取

投影到参考面的正弦光栅投影光强为:
在这里插入图片描述
经物体调制后的光强图为;
在这里插入图片描述
其中方程组共有N个方程,三个未知量,原理上当N>=3时可以求解。在实际中为保证精度一般取N>=4,使求解体系变为超定方程求解。
在这里插入图片描述
在这里插入图片描述
上面是N步相移的通用推导方式。下面以四步相移为例进行展示。
条纹投影时每个频率投影四幅图片,每幅图片之间的相移为pi/2则公式为:
在这里插入图片描述
可以联立方程组得:
在这里插入图片描述
此时相位的范围在(-pi/2,pi/2)之间,一般在matlab中使用atan2()将范围扩至(-pi,pi)。

解包裹(求取绝对相位)

解包裹算法很多,下面以时域解包裹算法中的多频外差进行介绍。以三频四相为例。
(三个频率,每个频率四幅图片)
因为我们要知道每个点的绝对相位,可以通俗理解为要知道在第几个周期的某个地方。
在这里插入图片描述
比如这副光栅图像中,在包裹相位中只能知道在当前周期的什么位置,却不知道处于第几周期。求取绝对相位就是确定在整幅图像中的位置。(第xx周期第xx列)
首先我们了解一下双频外差,即只有两个不同的频率。
在这里插入图片描述
在这里插入图片描述
Teq为等效周期也就是P12, T1为P1,T2为P2. 用两个不同的频率合成一个可以覆盖整幅图像的等效周期。三频外差的具体流程如下:
1.选择合适的三种条纹周期T1,T2,T3,满足T1< T2 < T3 < T12 < T23 < T123,且T123 > width则有
在这里插入图片描述
2.将得到的包裹相位缩放到【0,2*pi)之间
3.按照上式进行相位差分
在这里插入图片描述
证明如下在这里插入图片描述
在这里插入图片描述
4.因为T123已经可以覆盖整幅图像所以其中的相位可以认为为绝对相位。下面就是对某一包裹相位进行展开一般最后选择频率最高的进行相位展开,这是因为高频的信噪比比较高,误差较小。
在这里插入图片描述
这样我们就得到了调制以后的绝对相位。可以根据两个相位差进行物体形貌的复原。

  • 18
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是 C 代码: #include <stdio.h> #include <stdlib.h> #include <math.h> #define PI 3.14159265358979323846 int main() { int width, height, depth; printf("请输入条纹图的宽度、高度和深度:"); scanf("%d %d %d", &width, &height, &depth); int*** stripes = (int***)malloc(depth * sizeof(int**)); for (int i = ; i < depth; i++) { stripes[i] = (int**)malloc(height * sizeof(int*)); for (int j = ; j < height; j++) { stripes[i][j] = (int*)malloc(width * sizeof(int)); for (int k = ; k < width; k++) { printf("请输入第 %d 层第 %d 行第 %d 列的条纹值:", i + 1, j + 1, k + 1); scanf("%d", &stripes[i][j][k]); } } } double*** wrapped_phase = (double***)malloc(depth * sizeof(double**)); for (int i = ; i < depth; i++) { wrapped_phase[i] = (double**)malloc(height * sizeof(double*)); for (int j = ; j < height; j++) { wrapped_phase[i][j] = (double*)malloc(width * sizeof(double)); for (int k = ; k < width; k++) { wrapped_phase[i][j][k] = .; } } } for (int i = ; i < depth; i++) { for (int j = ; j < height; j++) { for (int k = ; k < width; k++) { if (k < width - 1) { wrapped_phase[i][j][k] += atan2(stripes[i][j][k + 1] - stripes[i][j][k], 1.); } if (j < height - 1) { wrapped_phase[i][j][k] += atan2(stripes[i][j + 1][k] - stripes[i][j][k], 1.); } if (i < depth - 1) { wrapped_phase[i][j][k] += atan2(stripes[i + 1][j][k] - stripes[i][j][k], 1.); } } } } double*** unwrapped_phase = (double***)malloc(depth * sizeof(double**)); for (int i = ; i < depth; i++) { unwrapped_phase[i] = (double**)malloc(height * sizeof(double*)); for (int j = ; j < height; j++) { unwrapped_phase[i][j] = (double*)malloc(width * sizeof(double)); for (int k = ; k < width; k++) { unwrapped_phase[i][j][k] = wrapped_phase[i][j][k]; } } } for (int i = ; i < depth; i++) { for (int j = ; j < height; j++) { for (int k = ; k < width; k++) { if (k > ) { double diff = unwrapped_phase[i][j][k] - unwrapped_phase[i][j][k - 1]; if (diff > PI) { unwrapped_phase[i][j][k] -= 2 * PI; } else if (diff < -PI) { unwrapped_phase[i][j][k] += 2 * PI; } } if (j > ) { double diff = unwrapped_phase[i][j][k] - unwrapped_phase[i][j - 1][k]; if (diff > PI) { unwrapped_phase[i][j][k] -= 2 * PI; } else if (diff < -PI) { unwrapped_phase[i][j][k] += 2 * PI; } } if (i > ) { double diff = unwrapped_phase[i][j][k] - unwrapped_phase[i - 1][j][k]; if (diff > PI) { unwrapped_phase[i][j][k] -= 2 * PI; } else if (diff < -PI) { unwrapped_phase[i][j][k] += 2 * PI; } } } } } printf("包裹相位为:\n"); for (int i = ; i < depth; i++) { for (int j = ; j < height; j++) { for (int k = ; k < width; k++) { printf("%f ", wrapped_phase[i][j][k]); } printf("\n"); } printf("\n"); } printf("展开相位为:\n"); for (int i = ; i < depth; i++) { for (int j = ; j < height; j++) { for (int k = ; k < width; k++) { printf("%f ", unwrapped_phase[i][j][k]); } printf("\n"); } printf("\n"); } for (int i = ; i < depth; i++) { for (int j = ; j < height; j++) { free(stripes[i][j]); free(wrapped_phase[i][j]); free(unwrapped_phase[i][j]); } free(stripes[i]); free(wrapped_phase[i]); free(unwrapped_phase[i]); } free(stripes); free(wrapped_phase); free(unwrapped_phase); return ; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值