参考博客
代码部分来源:多频外差法之三频四相的理论与实现(matlab)
前言
面结构光作为目前主流的非接触式三维测量方式,求相位是其非常关键的步骤。相位计算分为两步:相位主值计算和解相位包裹。
一、相位主值计算
1. 生成条纹
在该方法中,相位主值的计算依靠相移法来完成。相移法的基本原理就是通过采集多帧具有一定相移的条纹图案来计算相移主值。
在该方案中,条纹图像的光强为正弦分布,因此其光强公式为:
需要注意的是,在生成条纹时需要用如下公式:
其中A、B和Wp分布代表正弦条纹信号的偏移、幅度和周期数。W是投影仪分辨率的宽度。
2. 计算相位主值
当有了条纹图案后,再利用如下公式计算出其相位主值:
其计算步骤如下图所示。可以看到,计算出的相位是在[0,2π],一个相位值φ对应多个x值,因此需要将其展开,一个φ对应一个x。
解包裹在本文中使用的是多频外差法,在本文中选择三种不同频率的条纹做外差。
二、解相位包裹
利用多频外差法解包裹的原理如下图所示:
当解出三种不同频率的相位主值之后,两两做外差,分别求出12、23的相位,再通过12、23做外差求出解包裹的相位123的值。计算公式如下:
当获得了φ123的值之后(在上式中Δn=φ/2π),便可利用公式(6)对频率12进行解包裹,再利用解包裹的频率12和公式(7)求解绝对主值ϕ1(求解的绝对主值通常为最高频率)。至此,绝对相位计算完成。
%这个代码是横向条纹
% 程序开始
clc;
close all;
clear;
% 图片的初始化
width = 1024;
heigth = 768;
% 三频率
% 这个可以参见李中伟的博士论文
p = [1/70 1/64 1/59]; %像素单位为个数,可以看做频率;正弦函数为周期含义
T=[70 64 59]; %周期
%% step1 生成条纹图
% 利用分块矩阵C存储3组共计12张图
% 三种频率,四组相位
C = cell(3,4); %储存条纹图
for i=1:3
for j=1:4
C{i,j} = zeros(heigth,width);
end
end
% 利用余弦函数计算12张图的灰度值
% 图像的生成
% 三种频率,四组相位
for i = 1:3 % 对应三种不同的频率
for j = 0:3 % 对应四种相位
for k = 1:width
C{i,j+1}(:,k) = 128+127*cos(2*pi*k*T(i)/width+j*pi/2);%每一列一个条纹可能
%A = 128; % 调制强度
%B = 127; % 调制幅值
end
end
end
% 对灰度值进行归一化处理
for i = 1:3
for j = 1:4
C{i,j} = mat2gray(C{i,j});
end
end
%显示12张图
% for i = 1:3
% for j = 1:4
% n = 4*(i-1)+j;
% h = figure(n);
% imshow(C{i,j});
% end
% end
%% step2 相位主值
% 初始化三组处理后的图片灰度矩阵
% phi也是分块矩阵
% 存储相位主值图像
phi = cell(3,1); %储存相位主值
for i = 1:3
phi{i,1} = zeros(heigth,width);
end
% 求取相位差
% 计算每种频率对应的相位主值
% 输出三种频率的相位主值,用于相差计算
for i = 1:3 % 对于3组中的每一组图片,每一组相同频率的有四张图片
I1 = C{i,1};
I2 = C{i,2};
I3 = C{i,3};
I4 = C{i,4};
for g = 1:heigth
for k = 1:width
if I4(g,k)==I2(g,k)&&I1(g,k)>I3(g,k) %四个特殊位置
phi{i,1}(g,k)=0;
elseif I4(g,k)==I2(g,k)&&I1(g,k)<I3(g,k) %四个特殊位置
phi{i,1}(g,k)=pi;
elseif I1(g,k)==I3(g,k)&&I4(g,k)>I2(g,k) %四个特殊位置
phi{i,1}(g,k)=pi/2;
elseif I1(g,k)==I3(g,k)&&I4(g,k)<I2(g,k) %四个特殊位置
phi{i,1}(g,k)=3*pi/2;
elseif I1(g,k)<I3(g,k) %二三象限
phi{i,1}(g,k)=atan((I4(g,k)-I2(g,k))./(I1(g,k)-I3(g,k)))+pi;
elseif I1(g,k)>I3(g,k)&&I4(g,k)>I2(g,k) %第一象限
phi{i,1}(g,k)=atan((I4(g,k)-I2(g,k))./(I1(g,k)-I3(g,k)));
elseif I1(g,k)>I3(g,k)&&I4(g,k)<I2(g,k) %第四象限
phi{i,1}(g,k)=atan((I4(g,k)-I2(g,k))./(I1(g,k)-I3(g,k)))+2*pi;
end
end
end
end
% plot(phi{1,1}(1,:),'r'); %这是我画曲线的思路,我取了相位主值1的第一行
% hold on;
% plot(phi{2,1}(1,:),'b');
%% step3 解包裹
% 计算相差
% 保存矩阵,用于多频相差的计算
PH1 = phi{1,1}; %频率1
PH2 = phi{2,1}; %频率2
PH3 = phi{3,1}; %频率3
del_n1=PH1/(2*pi);
del_n2=PH2/(2*pi);
del_n3=PH3/(2*pi);
% 初始化相差变量
% 多频相差
del_n12 = zeros(heigth,width);
del_n23 = zeros(heigth,width);
del_n123 = zeros(heigth,width);
% 计算相差
% 相差计算
% 解相
for g = 1:heigth
for k = 1:width
% 计算第一组和第二组的相差
if del_n1(g,k)>=del_n2(g,k)
del_n12(g,k) = del_n1(g,k)-del_n2(g,k);
else
del_n12(g,k) = del_n1(g,k)+1-del_n2(g,k);
end
% 计算第二组和第三组的相差
if del_n2(g,k)>=del_n3(g,k)
del_n23(g,k) = del_n2(g,k)-del_n3(g,k);
else
del_n23(g,k) = del_n2(g,k)+1-del_n3(g,k);
end
% plot(1,k);
end
end
% 计算最终相差
% 相差图案
% 相位解包裹 相位展开
for g = 1:heigth
for k = 1:width
if del_n12(g,k)>=del_n23(g,k)
del_n123(g,k) = del_n12(g,k)-del_n23(g,k);
else
del_n123(g,k) = del_n12(g,k)+1-del_n23(g,k);
end
end
end
% 显示
% figure,imshow(mat2gray(del_n12*2*(pi)));title('1,2外差'); imwrite(mat2gray(del_n12),'12外差.bmp');
% figure,imshow(mat2gray(del_n23*2*(pi)));title('2,3外差'); imwrite(mat2gray(del_n23),'23外差.bmp');
% figure,imshow(mat2gray(del_n123*2*(pi)));title('1,2,3外差');imwrite(mat2gray(del_n123),'123外差.bmp');
% figure,imshow(mat2gray(del_n1*2*(pi)));title('1相位主值'); imwrite(mat2gray(del_n1),'1相位主值.bmp');
% figure,imshow(mat2gray(del_n2*2*(pi)));title('2相位主值'); imwrite(mat2gray(del_n2),'2相位主值.bmp');
% figure,imshow(mat2gray(del_n3*2*(pi)));title('3相位主值'); imwrite(mat2gray(del_n3),'3相位主值.bmp');
%% step4展开相位
%%生成fai1
%频率
p23=p(2)*p(3)/(p(3)-p(2));
p12=p(1)*p(2)/(p(2)-p(1));
p123=p12*p23/(p23-p12);
n12 = zeros(heigth,width);
n12 = p23*(del_n123)/(p23-p12);
% n12=-n12;
%figure,imshow(mat2gray(n12));
N12=floor(n12);
n1=p(2)*(N12+del_n12)/(p(2)-p(1));
N1=floor(n1);
fai1=zeros(heigth,width);
fai1=2*pi*(N1)+PH1;
a=mat2gray(fai1);
plot(a(1,:))
figure,imshow(mat2gray(fai1));title('fai1');
% plot(PH1(1,:),'r');
% hold on;
% plot(2*pi*N1(1,:),'b');
% hold on;
% plot(fai1(1,:),'g');
% s=2*pi*N1;
改代码最终求出了解包裹相位,得到连续的相位图。
绿色线条为相位值。
求出绝对相位后,要考虑如何将相位转换为高度,本人使用的是将投影仪转换为逆相机,将投影仪像素坐标系和相机像素坐标系对应起来。通过公式可知,投影仪坐标系的一点,可以通过投影横、纵条纹,由相机坐标系计算得到。
总结
本文讨论了如何利用三频四步法求解相位主值,总体来说,就是投影三种频率的图案,每一种频率的图案有四步相移,因此有3*4=12张图片。每种频率的4张图片通过公式计算出相位主值,但相位主值是包裹的,因此要通过外差法解包裹。在外差法里,先通过φ1与φ2、φ2与φ3做外差求出φ12和φ23,再通过φ12和φ23做外差求解出φ123。假设φ1的频率最高,此时可以通过φ123求解绝对相位ϕ12,再通过ϕ12计算出ϕ1.
参考文献
[1]基于数字光栅投影的结构光三维测量技术与系统研究_李中伟
[2]Xingjian Liu , Luhang Song , Mingkang Zhang , Haibo Liu , Te Li , Changhai Ru , Yongqing Wang,et al.2023.“3-D Structured Light Scanning With Phase Domain-Modulated Fringe Patterns”.IEEE Transactions on Industrial Electronics,70(5):5245-5254.https://doi.org/10.1109/TIE.2022.3187597
[3]Ji Li , Jingtian Guan , Hui Du ,and Juntong Xi.2021.“Error self-correction method for phase jump in multi-frequency phase-shifting structured light”.Applied Optics,60(4):949.https://doi.org/10.1364/AO.413506
[4]基于多频外差的全频解相方法_刘飞