前言:理论部分可看上篇文章:结构光三维重建(四步相移&多频外差法)matlab实现(一)
Matlab代码实现正弦条纹生成,四步相移,三频外差:
项目结构:
main.m :
clc;
close all;
clear;
width =1240; %生成图的宽
height =1110; %高
A=0.5;
B=0.5;
WaveLengthArr= [70,64,59];
nStepPS=4;
xArr = [1:height];
%% 三频四步条纹生成
StdFringeSet = GetFringeSet(height, width, nStepPS, WaveLengthArr, 0,A,B);
%% 相位主值计算及三频外差展开
Phase_fring = PhaseDemodulate4StepPS(StdFringeSet);
% imagesc(b):将数组b中的数据显示为一个图像,该图像使用颜色图中的全部颜色。
% b中的每个元素指定图像的一个像素的颜色。生成图像是m*n的像素网格,其中m,n分别为c中的行数和列数。
% figure:创建默认图窗
GetFringeSet.m:
% 在MATLAB中,函数定义在单独的文件。函数和函数的文件名应该是相同的。
%% Fringes generation
% 生成四张正弦条纹图
function [FringeSet] = GetFringeSet(height, width, nStepPS, WaveLengthArr, ObjectHeight,A,B)
FringeSet = cell(3,4); %建立一个三行的二维数组
xArr = [1:height];
yArr = [1:width];
[yGrid, xGrid] = meshgrid(yArr, xArr); % meshgrid用于绘制等高线 xGrid=yGrid=1110*1240
for iWavelength = 1:length(WaveLengthArr) % 定义变量iWavelength,从1循环到length(WaveLengthArr)=[15]
WaveLength = WaveLengthArr(iWavelength);% WaveLength=64 像素周期为64
for iStepPhaseshift = 1:nStepPS % nStepPS=4
% Phase =2*pi*(xGrid+ObjectHeight)/WaveLength; 实验一,生成条纹周期为70
Phase =2*pi*(xGrid+ObjectHeight)/(height/WaveLength); %实验二,整张图像生成70条条纹,即条纹宽度,周期为:heigh/70
Phase = Phase + (iStepPhaseshift-1)* (2*pi/nStepPS) ; %四位相移法,每次移动2π/4
Fringe2D = A+B*cos(Phase); %cos输入弧度参数 π=3.1415926... ,cos{ 2π/(1+)64} 因此以64为周期
% figure, imagesc(Fringe2D); colormap gray; axis image;
FringeSet{iWavelength,iStepPhaseshift} = Fringe2D;
filename = sprintf('%0.2d_%0.2d.bmp', WaveLength, iStepPhaseshift);
% mat2gray 将矩阵 A 转换为灰度图像 I,该图像包含 0(黑色)到 1(白色)范围内的值。
imwrite(mat2gray(Fringe2D),filename,'bmp');
end
end
PhaseDemodulate4StepPS.m :
% 求得光栅相位主值
function [phaseMapS] = PhaseDemodulate4StepPS(FringeSet)
%PHASEDEMODULATE4STEPPS Summary of this function goes here
% Detailed explanation goes here
for i = 1:size(FringeSet)
middle=FringeSet(i,:);
phaseMap = atan2((middle{4} - middle{2}),(middle{1} - middle{3}));
%将截断相位映射到0~2π
phaseMap(phaseMap<0)=phaseMap(phaseMap<0)+2*pi;
%figure,imagesc(phaseMap);
%figure,mesh(phaseMap);
phaseMapS{i}=phaseMap;
end
% 三频外差法:光栅相位展开(解包裹)
phase1=phaseMapS{1};
phase2=phaseMapS{2};
phase3=phaseMapS{3};
% 70,64,59
T= [1/70,1/64,1/59];
% 求解等效周期
T12 = (T(1) * T(2)) / (T(2) - T(1));%1/6
T23 = (T(2) * T(3)) / (T(3) - T(2));%1/5
T123 = (T12 * T23) / (T23 - T12);%1
% 计算外差
phase12=phase1-phase2;
phase12(phase12<0)=phase12(phase12<0)+2*pi;
filename = sprintf('phase12.bmp');
% mat2gray 将矩阵 A 转换为灰度图像 I,该图像包含 0(黑色)到 1(白色)范围内的值。
imwrite(mat2gray(phase12),filename,'bmp');
phase23=phase2-phase3;
phase23(phase23<0)=phase23(phase23<0)+2*pi;
filename = sprintf('phase23.bmp');
% mat2gray 将矩阵 A 转换为灰度图像 I,该图像包含 0(黑色)到 1(白色)范围内的值。
imwrite(mat2gray(phase23),filename,'bmp');
phase123=phase12-phase23;
phase123(phase123<0)=phase123(phase123<0)+2*pi;
filename = sprintf('phase123.bmp');
% mat2gray 将矩阵 A 转换为灰度图像 I,该图像包含 0(黑色)到 1(白色)范围内的值。
imwrite(mat2gray(phase123),filename,'bmp');
% 求解参考面的绝对相位选择频率最高的那个
% 这里要注意求解顺序,要先用求的得pha_W123这个绝对相位对pha_W23或者pha_W12进行展开,
% 再利用已经展开的绝对相位展开pha_W1,pha_W2,pha_W3 对参考平面的展开也是如此
Ox_12 = round((phase123*T123/T12 - phase12)/ (2*pi) );
pha_TC12 = phase12 + 2*pi*Ox_12;
Ox_1= round((pha_TC12*T12/T(1) - phase1)/ (2*pi));
pha_TC1 = phase1 + 2*pi*Ox_1;
figure,imagesc(pha_TC1);
figure,mesh(pha_TC1);
figure,plot(pha_TC1);
% [hang,lie]=size(phase12); % 1110高 1240宽
end
实验结果:
解包裹相位: