EE630 PROJECT 3D OVERVIEW OF PHASE MEASURING PROFILOMETRY STRUCTURED LIGHT ILLUMINATION by LGH

advertisement
EE630 PROJECT 3D
OVERVIEW OF PHASE MEASURING PROFILOMETRY STRUCTURED LIGHT
ILLUMINATION
by LGH
11-7-2014
Updated 11-10-2014:
We introduce you to a Structured Light Illumination (SLI) method known as Phase Measuring
Profilometry (PMP). In this method we analyze each pixel of the captured pattern sequence as a
temporal signal. Each signal is exactly one cycle long. From the phase shift we can determine the
depth of the surface at that pixel. Our coordinate system is comprised of the phase dimension
(vertical axis) and the orthogonal dimension (horizontal axis). We are using a dual-frequency
version of PMP where we first project patterns with a long spatial period or what we refer to as
the baseline kc=1 pattern set. The baseline set of patterns yields a non-ambiguous phase result
which tends to be noisy and sometimes distorted. To reduce the noise and distortion we project a
second set of patterns which are higher frequency along the phase dimension. The second set
yields a wrapped phased result which is lower in noise but ambiguous in depth. So the first
baseline phase is used to unwrap the second wrapped phase result yielding both a precise surface
measure and non-ambiguous depth. The unwrapped phase images are converted to 3-D
coordinates via perspective transformations found from a calibration data set.
1. INPUT TARGET DATA
Given a sequence of 24 bit BMP files, we generate an inphase and quadrature phase image
pattern.
Figure 1: Last captured image in sequence.
1
Fig. 1 shows the mannequin “Fred” with sinusoidal pattern projected at an angle from the
camera’s optical axis. Figs 2 and 3 show the complete 32 pattern sequence for the baseline and
second frequency sequences, respectively.
Figure 2: Baseline frequency kc=1 image sequence.
Notice the spatial movement of the pattern across the FOV. For the baseline image sequence, the
spatial period is greater than the vertical distance of the FOV.
The second frequency set is shown in Fig. 2. The frequency and number of patterns are set up in
MATLAB as:
clear all;
Nf = 2; % number of different frequencies
Nk(1)=1; % kc0=1 (k=0) first of Nf frequences
Np(1)=32; % number pattern shifts for first frequency
Nk(2)=16; % kc1=16 (k=1) second of Nf frequences
Np(2)=32; % number pattern shifts for second frequency
2
Figure 3: Second frequency (kc=16)
File names, sizes, initialization of phase, albedo and indicator images are given by
Pathname='Data3D' % path or folder name in reference to your default path
Filename='pattern' % name of files not including the index or suffix
Filesuffix='bmp' % suffix or image type
index=0; % first index is 0
Fullname=sprintf('%s%c%s%d%c%s',Pathname,'\',Filename,index,'.',Filesuffix);
A_bmp=double(imread(Fullname)); % load pattern#.bmp
[My, Nx, Pz] =size(A_bmp);
My
Nx
Pz
Phase0=zeros(My,Nx);
Phase1=zeros(My,Nx);
AlbedoC=zeros(My,Nx);
AlbedoI=zeros(My,Nx);
For both frequencies, the number of patterns is 32. We will form a phase image for both
frequencies, albedo image as the average of all patterns and an indicator image based only on the
second frequency. In addition to this, the second phase image will be unwrapped during the input
process. The entire code is as follows:
index=0; % first index is 0
3
for k=1:Nf; % frequency group
Iq=zeros(My,Nx);
Ii=zeros(My,Nx);
for p=1:Np(k);
Fullname=sprintf('%s%c%s%d%c%s',Pathname,'\',Filename,index,'.',Filesuffix);
A_bmp=double(imread(Fullname)); % load pattern#.bmp
Ar=A_bmp(:,:,1);
%%
if k==1
figure(2);
else
figure(3);
end;
subplot(8,4,p,'align');
imagesc(Ar);
colormap gray
axis image;
axis off
%title('Captured Pattern Sequence');
% average in albedo
AlbedoC=AlbedoC+Ar;
% determin the sin and cos phase shift coefficients
sincoef=sin(2*pi*(p-1)/Np(k));
coscoef=cos(2*pi*(p-1)/Np(k));
% average in weighted quadrature and inphase images
Iq=Iq+Ar.*sincoef;
Ii=Ii+Ar.*coscoef;
% increment to next pattern
index=index+1;
end; % loop over p
figure(2);
print -dtiff 'B_SubplotsOfBaselineFreq.tif';%%
figure(3);
print -dtiff 'C_SubplotsOfSecondFreq.tif';%%
if Np(k)>1 & k==Nf
Iq=Iq/Np(k);
Ii=Ii/Np(k);
end;
% process first set of patterns into phase image
if k==1
Phase0=atan2(Iq,Ii)+pi;
end;
AlbedoI=sqrt(Ii.*Ii+Iq.*Iq); % calculate the peak to peak response of
patterns
% process second set of patterns into phase image
if k==2
Phase1=atan2(Iq,Ii)+pi;
%Phase unwrapping
%Phase cycles
Cycle0=floor((Nk(2)*Phase0-Phase1)/(2*pi));
% find cycle remainder between unwrapped phase1 and Phase0
remainder=((Nk(2)*Phase0-Phase1)-Cycle0*2*pi)/(2*pi);
% find where remainder (phase distance) is greater than +1/2 cycle,
Iplus=find(remainder>0.5);
Cycle0(Iplus)=Cycle0(Iplus)+1;
% find where remainder (phase distance) is less than -1/2 cycle,
4
Iminus=find(remainder<-0.5);
Cycle0(Iminus)=Cycle0(Iminus)-1;
% put unwrapping Cycle0 back to radians and add original Phase 1
Phase00=(Cycle0*2*pi)/Nk(2);
Phase00=Phase00+(Phase1/Nk(2));
end
end; % loop over k
2. GENERATE PHASE, ALBEDO AND INDICATOR IMAGES
In this section we will describe the mathematics behind the code presented in section 1. Let the
kth frequency, nth shifted pattern image captured by the camera is represented as Ik,n(x,y) where x
and y are the column and row pixel locations, respectively. The indices are k = 0, (Nf -1) and n =
0, 1, … (N-1) where Nf =2 and N=32. The two frequencies are kc0=1 and kc1=16.
2.1 Albedo Image
Technically the albedo refers to the reflectance of the target surface independent of local
gradient. We will use the term more loosely by simply representing the average reflectance
across all pattern sequences. To find the albedo image C.bmp, average the pattern images
together and scale between 0 and 255;
I C  x, y  
1
Nf N
N f N 1
 I
k ,n
 x, y 
(2.1)
k 0 n  0
The code for this, given in the first section is:
% average in albedo
AlbedoC=AlbedoC+Ar;
where “Ar” is the input image intensity. The result is shown in Fig. 4.
Figure 4: Average image intensity or "Albedo."
5
2.2 In-phase and Quadrature Image Information
Along with image intensity we determine what is basically the “inphase” component and the
“quadrature” component of the temporal signal at each pixel. The inphase term is
I In,k x, y  
N 1
I
k ,n
x, y cos2n / N 
(2.2)
n 0
and the quadrature component image is
I Quad ,k x, y  
N 1
I
k ,n
x, y sin2n / N 
(2.3)
n 0
The matlab code for the inphase and quadrature images is
% determin the sin and cos phase shift coefficients
sincoef=sin(2*pi*(p-1)/Np(k));
coscoef=cos(2*pi*(p-1)/Np(k));
% average in weighted quadrature and inphase images
Iq=Iq+Ar.*sincoef;
Ii=Ii+Ar.*coscoef;
2.3 Indicator and Phase images
Given the in-phase and quadrature images, we can generate the indicator image and the various
phase images. The indicator matrix I, in I.bmp, is based on the modulation amplitude [1] of the
patterns such that:
I I  x, y  
I In,k x, y 2  I Quad ,k x, y 2
(2.4)
where the k value selects the highest frequency pattern set. The matlab code is:
if Np(k)>1 & k==Nf
Iq=Iq/Np(k);
Ii=Ii/Np(k);
end;
AlbedoI=sqrt(Ii.*Ii+Iq.*Iq); % calculate the peak to peak response of
An example is shown in Fig. 5.
6
Figure 5: Indicator image.
The phase image for the baseline k=0 and the high frequency k=1 are determined by
 I Quad ,k x, y  
 k x, y   arctan 
 
 I In,k x, y  
(2)
For implementation, you should use atan2(y,x) instead of atan(y/x) because atan() only yields
values for 2 quadrants where as atan2() yields angles spanning all 4 quadrants. The  is added to
make the phase go from 0 to 2 rather than – to . The baseline phase is shown in Fig. 6 (left)
and the high frequency phase is shown in Fig. 6 (right).
Figure 6: (left) Phase k=0 and (right) phase k=1.
If we take a cross section of both phase images in Fig. 6, we plot together, shown in Fig. 7, we
can see that the k=0 phase is non-ambiguous where as the k=1 is wrapped. Both vary from 0 to
2.
7
Figure 7:(blue) Phase k=0 cross section and (green) phase k=1 cross section.
In preparation to unwrap k=1, we normalize it by dividing by its pattern spatial frequency of kc =
16 and offsetting first wrap section.
Figure 8: (blue) Phase k=0, (green) phase k=1 divided by its projected spatial frequency of kc1=16 cycles per FOV and
(red) the unwrapped phase.
As seen in Fig. 8, the phase gradients of the (k=0) kc0=1 and (k=1) kc1=16 are about the same
when normalized. We need to use k=0 phase to estimate how many integer multiples of 2 to
align the k=1 phase with the k=0 phase. Once that is done, the k=0 phase is not included in the
final phase estimate, thus removing its noise contribution.
The first step [2] is to obtain the integer number of phase unwrapping wavelengths (unwrapping
cycles) that are at or below the desired value such that
 x , y   floor k c 1 0 x , y    1 x , y  / 2 
(3)
In units of cycles, we find the difference between the baseline phase and the unwrapping cycles
such that
8
r  x, y   k c 1 0 x , y    1 x , y   2   x, y  / 2
(4)
A final adjustment of +/- 1 unwrapping cycle is done by evaluating the remainder such that
  x, y   1 for r  x, y   0.5
u x, y   
  x, y   1 for r x, y    0.5
(5)
The final phase image is then the unwrapping cycles plus the higher frequency phase such that
  x , y   2 u  x , y    1  x, y  / k c 1
(6)
Thus, the k=1 phase is unwrapped and shown in Fig. 8.
Figure 9: Unwrapped phase image.
The matlab code for the unwrapping is:
if k==1
Phase0=atan2(Iq,Ii)+pi;
end;
AlbedoI=sqrt(Ii.*Ii+Iq.*Iq); % calculate the peak to peak response of
patterns
% process second set of patterns into phase image
if k==2
Phase1=atan2(Iq,Ii)+pi;
%Phase unwrapping
%Phase cycles
Cycle0=floor((Nk(2)*Phase0-Phase1)/(2*pi));
% find cycle remainder between unwrapped phase1 and Phase0
remainder=((Nk(2)*Phase0-Phase1)-Cycle0*2*pi)/(2*pi);
% find where remainder (phase distance) is greater than +1/2 cycle,
Iplus=find(remainder>0.5);
Cycle0(Iplus)=Cycle0(Iplus)+1;
% find where remainder (phase distance) is less than -1/2 cycle,
Iminus=find(remainder<-0.5);
Cycle0(Iminus)=Cycle0(Iminus)-1;
% put unwrapping Cycle0 back to radians and add original Phase 1
Phase00=(Cycle0*2*pi)/Nk(2);
Phase00=Phase00+(Phase1/Nk(2));
9
end
3. CONVERTING PHASE TO 3-DIMENIONSIONAL COORDINATES
To map the C, I and phase matrices to C, I, and X, Y, Z coordinates we start with the calibration
data stored in the G file to determine the M matrix of coefficients (we will provide this for you).
A linear triangulation paper will be provided with the assignment for explanation. Include M
values in your report.
The world to camera coordinate transforms for a pin hole lens are
xc,n 
m1 x w,n  m 2 y w,n  m3 z w,n  m 4
m9 x w, n  m10 y w,n  m11 z w,n  m12
(7)
and
y c,n 
m 5 x w , n  m 6 y w , n  m 7 z w , n  m8
m9 x w,n  m10 y w,n  m11 z w,n  m12
(8)
where n=1, 2, …. N known points. Because there is an unknown coefficient with every term in
the above transformations, there are an infinite number of solutions. However, if we make
m12  1 then the transformation is linear at the world origin so we fix the common coefficient
value of m12 to be unity such that
m12  1
(9)
A coefficient vector, not including the m12 coefficient is defined as 11x1 column vector such that
T
m  m1 m2 m3 m4 m5 m6 m7 m8 m9 m10 m11 
(10)
Given a linear equation as
p Am
(11)
where
p 
p   zxc 
 p zyc 
(12)
is a 2Nx1 vector constructed from the augmentation of two Nx1 vectors given by
T
p zxc  m12 x c , n ... m12 x c , N 
(13)
and
p zyc  m12 y c ,n
(14)
... m12 y c , N 
T
The factor matrix A is 2Nx11 and constructed by the augmentation of two matrices as
10
 A xc 
A 
 A yc 
(15)
where
A xc
 x w,1

 .
 x w, N
y w,1
z w,1
.
.
y w, N
z w, N
1 0 0 0 0
.
.
.
.
.
 xc ,1 x w,1
 xc ,1 y w,1
.
.
1 0 0 0 0  xc , N x w, N
 x c , N y w, N
 xc ,1 z w,1 

.

 xc , N z w, N 
(16)
 y c ,1 z w,1 

.

 y c , N z w, N 
(17)
and
A yc
0 0 0 0 x w,1

.
 . . . .
0 0 0 0 x w, N
y w,1
z w,1
1
 y c ,1 x w,1
 y c ,1 y w,1
.
.
.
.
.
y w, N
z w, N
1  y c , N x w, N
 y c , N y w, N
The Least Squares Solution for the coefficient vector is

m  AT A

1
AT p
(18)
Use the M matrix of coefficients to reconstruct the 3-D surface (we provide this MATLAB code
as well).
While the solution to the coefficient values is a linear solution, the pin hole model perspective
correction is in no way linear because of the denominators dependency on world coordinates. So
to determine the world coordinates from the camera and projector coordinates is not exactly a
linear solution. That is, the solution is a matrix vector operation, it is not a linear combination of
the input camera and projector coordinates.
By algebraically manipulating the world to camera coordinate transforms and world to projector
coordinates to group together the world coordinates as
x c , n m12  m 4  m1  m9 x c , n  x w, n  m 2  m10 x c ,n  y w,n  m3  m11 x c ,n  z w,n
(19)
and
y c ,n m12  m8  m5  m9 y c ,n  x w, n  m6  m10 y c ,n  y w,n  m7  m11 y c , n  z w,n
(20)
and the projector phase is reconfigured as
y p ,n m PA12  m PA8  m PA 5  m PA9 y p ,n  x w,n  m PA 6  m PA10 y p ,n  y w,n  m PA 7  m PA11 y p ,n  z w,n
(21)
Let the left side of Eqs. (19) thru (21) be combined into the matrix
11
 xc ,n m12  m 4 


Dn   y c ,n m12  m8 
 y p , n m PA12  m PA8 


(22)
and combine the coefficients from the right side as
 m1  m9 xc ,n

C n   m5  m9 y c , n
m PA5  m PA9 y p , n

m2  m10 x c , n
m3  m11 x c ,n
m6  m10 y c , n
m7  m11 y c ,n
m PA6  m PA10 y p ,n
m PA7  m PA11 y p ,n





(23)
The world coordinate vector is defined as
PnW  x w,n
y w, n
z w, n 
T
(24)
The linear algebraic solution for the world coordinate is then
PnW  C n1 Dn
(25)
Save the C,I, X,Y,Z data to mat5 format and then view in mat5 viewer. Use print screen to
capture image for this report.
Figure 10: GL3DView program displaying mat5 of Fred.
The code for creating the MAT 5 data is as follows:
12
%Albedo0=Albedo0/index;
ImageI=uint8(AlbedoI*2);
ImageC=uint8(AlbedoC/index);
% plot out data
figure(4);
imagesc(ImageC);
colormap gray;
axis image;
title('Image C (average intensity)');
print -dtiff 'D_AverageIntensity.tif';%%
figure(5);
imagesc(ImageI);
colormap gray;
axis image;
title('Image I (p-p intensity)');
print -dtiff 'E_QualityImage.tif';%%
figure(6);
imagesc(Phase0);
colormap gray;
axis image;
title('kc=1 Phase Image');
print -dtiff 'F_BaselinePhase.tif';%%
figure(7);
imagesc(Phase1);
colormap gray;
axis image;
title('Wrapped Phase Image');
print -dtiff 'G_WrappedPhase.tif';%%
figure(8);
imagesc(Phase00);
colormap gray;
title('Unwrapped Phase Image');
print -dtiff 'H_UnWrappedPhase.tif';%%
%
P0(1:My)=Phase0(1:My,Nx/2);
P1(1:My)=Phase1(1:My,Nx/2);
P00(1:My)=Phase00(1:My,Nx/2);
m=1:My;
figure(9);
plot(m,P0,m,P1);
title('kc=1 and kc=16 phase cross section');
print -dtiff 'I_PhaseCrossSection.tif';
figure(10);
P1A=P0(1)/Nk(1)+P1/Nk(2);
plot(m,P0/Nk(1),m,P1A,m,P00);
title('Multi-frequency phase vs. kc=1');
legend('baseline phase','f=16 phase','multi-f phase');
print -dtiff 'J_SuperimposedCrossSections.tif';
%% data image file OUTPUTS
13
B_bmp(:,:,1)=ImageC;
B_bmp(:,:,2)=ImageC;
B_bmp(:,:,3)=ImageC;
bmpimageC=B_bmp;
B_bmp(:,:,1)=ImageI;
B_bmp(:,:,2)=ImageI;
B_bmp(:,:,3)=ImageI;
bmpimageI=B_bmp;
imwrite(bmpimageC,'Albedo.bmp','BMP');
%
Albedo8=uint8(Phase0*255/(2*pi));
max(max(Albedo8))
min(min(Albedo8))
B_bmp(:,:,1)=Albedo8;
B_bmp(:,:,2)=Albedo8;
B_bmp(:,:,3)=Albedo8;
imwrite(B_bmp,'Phase0.bmp','BMP');
%
Albedo8=uint8(Phase1*255/(2*pi));
max(max(Albedo8))
min(min(Albedo8))
B_bmp(:,:,1)=Albedo8;
B_bmp(:,:,2)=Albedo8;
B_bmp(:,:,3)=Albedo8;
imwrite(B_bmp,'Phase1.bmp','BMP');
%
Albedo8=uint8(Phase00*255/(2*pi));
max(max(Albedo8))
min(min(Albedo8))
B_bmp(:,:,1)=Albedo8;
B_bmp(:,:,2)=Albedo8;
B_bmp(:,:,3)=Albedo8;
imwrite(B_bmp,'PhaseYP.bmp','BMP');
result=CPleastsqmethod();
%
out=getWorldCoordsB(ImageI,Phase00,32);
xw=out(:,:,1);
yw=out(:,:,2);
zw=out(:,:,3);
mat5file='fred';
result = mat5write(mat5file,bmpimageC,bmpimageI,xw,yw,zw);
result = mat52fileF(mat5file,bmpimageC,ImageI,xw,yw,zw);
REFERENCES
1. P.S. Huang, Q. Hu, F. Jin, F.P. Chiang, “Color-encoded digital fringe projection
technique for high-speed three-dimensional surface contouring,” Optical Engineering
38(6), pp 1065-1071, (June 1999)
2. Jielin Li, L.G. Hassebrook and Chun Guan, “Optimized Two-Frequency Phase-MeasuringProfilometry Light-Sensor Temporal-Noise Sensitivity,” JOSA A, 20(1), 106-115, (2003).
14
3. Kai Liu, Yongchang Wang, D.L. Lau, Q. Hao and L.G. Hassebrook, “Gamma model and
its analysis for phase measuring profilometry,” JOSA A, In press, (2011).
APPENDIX: MATLAB
READ IN MAT5 (mat5read.m)
% Veeraganesh Yalla
% template script to read the
% MAT5 files
% Date: Jan 30 2004
function [xw,yw,zw,imageI,imageC] = mat5read(matfile);
% open the world coordinate
% files
% the x,y,z are 1-D arrays
% need to be reshaped based on
% the dimensions of I and C images
fnamex = strcat(matfile,'X.byt');fnamey = strcat(matfile,'Y.byt');
fnamez = strcat(matfile,'Z.byt');fnameC = strcat(matfile,'C.bmp');
fnameI = strcat(matfile,'I.bmp');
%
fpx = fopen(fnamex,'rb');x = fread(fpx,'float');fclose(fpx);
%
fpy = fopen(fnamey,'rb');y = fread(fpy,'float');fclose(fpy);
%
fpz = fopen(fnamez,'rb');z = fread(fpz,'float');fclose(fpz);
%open the I and C images
imageC = imread(fnameC);imageI = imread(fnameI);
%get the dimensions
[my,nx,pz] = size(imageI);
%reshape the 1D world coordinate vectors
xw = reshape(x,nx,my)';
yw = reshape(y,nx,my)';
zw = reshape(z,nx,my)';
READ IN CALIBRATION FILE *G.byt (read_calib_data.m)
%
read the calibration data
%
function needs the input calibration grid data file '.byt'
%
Npoints number of calibration points
function [coods] = read_calib_data(infname,Npoints)
%
fp = fopen(infname,'rb');
calib_data = fread(fp,'float')
fclose(fp);
%read the coordinate information
[m,n] = size(calib_data);
coods = calib_data(2:m);
coods = reshape(coods,7,Npoints)';
%
ASCII FORMAT OF calgridG.byt
Note that the data below is for a grid that has “Npoint” = 28 points. The “npoint” indicates the
last point set being edited and carries no information in itself. Each line of data or point set has 7
15
floating point values. Going from left to right, they are Xw, Yw, Zw, Xc, Yc, Xp, Yp where “w”
indicates a world coordinate, “c” indicates a camera coordinate and “p” indicates a projector
coordinate. Notice that Xp’s are all 0 because this is not used in the reconstruction of the 3-D data
for most applications.
Npoint=28
npoint=0
0.000000 0.000000 0.000000 937.007996 1490.270020 0.000000 4.174830
0.000000 15.875000 0.000000 935.841003 1260.900024 0.000000 3.619083
0.000000 31.750000 0.000000 934.781982 1027.890015 0.000000 3.059905
0.000000 47.625000 0.000000 933.473999 796.344971 0.000000 2.512760
15.875000 0.000000 12.700000 1178.099976 1512.079956 0.000000 3.981830
15.875000 15.875000 12.700000 1176.050049 1278.420044 0.000000 3.413457
15.875000 31.750000 12.700000 1178.459961 1040.170044 0.000000 2.843287
15.875000 47.625000 12.700000 1176.650024 800.879028 0.000000 2.280516
31.750000 0.000000 0.000000 1397.069946 1484.609985 0.000000 4.176435
31.750000 15.875000 0.000000 1397.150024 1257.400024 0.000000 3.619735
31.750000 31.750000 0.000000 1396.910034 1025.890015 0.000000 3.062361
31.750000 47.625000 0.000000 1396.810059 795.119995 0.000000 2.511117
47.625000 0.000000 12.700000 1647.489990 1504.859985 0.000000 3.982054
47.625000 15.875000 12.700000 1648.849976 1271.560059 0.000000 3.409640
47.625000 31.750000 12.700000 1648.719971 1036.400024 0.000000 2.840146
47.625000 47.625000 12.700000 1649.569946 800.890991 0.000000 2.282020
63.500000 0.000000 0.000000 1848.689941 1479.130005 0.000000 4.177021
63.500000 15.875000 0.000000 1850.829956 1252.540039 0.000000 3.619135
63.500000 31.750000 0.000000 1851.040039 1023.830017 0.000000 3.064629
63.500000 47.625000 0.000000 1851.250000 795.603027 0.000000 2.514975
79.375000 0.000000 12.700000 2106.350098 1500.050049 0.000000 3.987183
79.375000 15.875000 12.700000 2110.250000 1265.739990 0.000000 3.405886
79.375000 31.750000 12.700000 2111.489990 1032.670044 0.000000 2.839072
79.375000 47.625000 12.700000 2113.550049 799.932007 0.000000 2.285129
95.250000 0.000000 0.000000 2292.300049 1472.890015 0.000000 4.178957
95.250000 15.875000 0.000000 2294.800049 1248.540039 0.000000 3.622159
95.250000 31.750000 0.000000 2297.090088 1021.719971 0.000000 3.066538
95.250000 47.625000 0.000000 2300.159912 796.306030 0.000000 2.518003
WRITE IN MAT5 (mat5write.m)
function [result] = mat5write(matfile,xw,yw,zw,imageI,imageC);
% open the world coordinate files
fnamex = strcat(matfile,'X.byt');fnamey = strcat(matfile,'Y.byt');
fnamez = strcat(matfile,'Z.byt');fnameC = strcat(matfile,'C.bmp');
fnameI = strcat(matfile,'I.bmp');
%get the dimensions
[my,nx,pz] = size(imageI);
%reshape the 1D world coordinate vectors
x = reshape(xw',1,my*nx)';y = reshape(yw',1,nx*my)';z =
reshape(zw',1,nx*my)';
%xw
fpx = fopen(fnamex,'wb');fwrite(fpx,x,'float32');fclose(fpx);
%yw
fpy = fopen(fnamey,'wb');fwrite(fpy,y,'float32');fclose(fpy);
%zw
fpz = fopen(fnamez,'wb');fwrite(fpz,z,'float32');fclose(fpz);
%C
16
imwrite(imageC,fnameC,'bmp');imwrite(imageI,fnameI,'bmp');
%
result = 1;
LEAST SQUARES METHOD FOR M MATRIX (result=CPleastsqmethod())
%% Generates the perspective matrix M parameters given the calibration data
function
out=CPleastsqmethod();
% to read data from G.byt file %
infname='CalgridG.byt';
fid=fopen(infname);
G=fread(fid,'float');
fclose(fid);
%no of elements%
%n=G(1);
%A=reshape(G(2:141),7,20)';
A=read_calib_data(infname,18);
%reading the world coordinates%
xw=A(:,1);
yw=A(:,2);
zw=A(:,3);
%reading the camera coordinates%
xc=A(:,4)
yc=A(:,5)
%reading the projector coordinates%
xp=A(:,6);
yp=A(:,7)
%%%calculate transformation matrix using linear triangulation%%%
%%%perspective matrix for camera%%%%
N=18;
for i=1:N
Ac(2*i-1,:)=[xw(i) yw(i) zw(i) 1 0 0 0 0 -xc(i)*xw(i) -xc(i)*yw(i) xc(i)*zw(i)];
Ac(2*i,:)=[0 0 0 0 xw(i) yw(i) zw(i) 1 -yc(i)*xw(i) -yc(i)*yw(i) yc(i)*zw(i)];
Pc(2*i-1,1)=xc(i);
Pc(2*i,1)=yc(i);
end
mc=(inv(Ac'*Ac))*Ac'*Pc;
mc(12)=1;
mwc=(reshape(mc,4,3))';
%%%perspective matrix for projector%%%%
for i=1:N
Ayp(i,:)=[xw(i) yw(i) zw(i) 1 -yp(i)*xw(i) -yp(i)*yw(i) -yp(i)*zw(i)];
Pp(i,1)=yp(i);
end
mp=(inv(Ayp'*Ayp))*Ayp'*Pp;
mp(8)=1;
mwp=(reshape(mp,4,2))';
17
%%%%%reconstruct the 3D world co-ordinates%%%%%
M=18;
for i=1:M
c(1,1)=mwc(1,1)-mwc(3,1)*xc(i);
c(1,2)=mwc(1,2)-mwc(3,2)*xc(i);
c(1,3)=mwc(1,3)-mwc(3,3)*xc(i);
c(2,1)=mwc(2,1)-mwc(3,1)*yc(i);
c(2,2)=mwc(2,2)-mwc(3,2)*yc(i);
c(2,3)=mwc(2,3)-mwc(3,3)*yc(i);
c(3,1)=mwp(1,1)-mwp(2,1)*yp(i);
c(3,2)=mwp(1,2)-mwp(2,2)*yp(i);
c(3,3)=mwp(1,3)-mwp(2,3)*yp(i);
d(1,1)=xc(i)-mwc(1,4);
d(2,1)=yc(i)-mwc(2,4);
d(3,1)=yp(i)-mwp(1,4);
W(:,i)=inv(c)*d;
end
new_xw(:,1)=W(1,:);
new_yw(:,1)=W(2,:);
new_zw(:,1)=W(3,:);
pdisplay=zeros(18,3);
olddisplay=pdisplay;
pdisplay(:,1)=new_xw(:,1);
pdisplay(:,2)=new_yw(:,1);
pdisplay(:,3)=new_zw(:,1);
olddisplay(:,1)=xw;
olddisplay(:,2)=yw;
olddisplay(:,3)=zw;
pdisplay
olddisplay
errval(:,1)= xw-new_xw(:,1);
errval(:,2)= yw-new_yw(:,1);
errval(:,3)= zw-new_zw(:,1)
%
erval = sqrt(errval(:,1).^2+errval(:,2).^2+errval(:,3).^2)
meanerval=mean(erval)
%write the projector parameters
fp = fopen('proj.txt','w');
fprintf(fp,'%f ',mwp(1,1));fprintf(fp,'%f ',mwp(1,2));fprintf(fp,'%f
',mwp(1,3));fprintf(fp,'%f\n',mwp(1,4));
fprintf(fp,'%f ',mwp(2,1));fprintf(fp,'%f ',mwp(2,2));fprintf(fp,'%f
',mwp(2,3));fprintf(fp,'%f\n',mwp(2,4));
%fprintf(fp,'%f ',mwp(3,1));fprintf(fp,'%f ',mwp(3,2));fprintf(fp,'%f
',mwp(3,3));fprintf(fp,'%f\n',mwp(3,4));
fclose(fp);
%write the camera parameters
18
fp = fopen('cam.txt','w');
fprintf(fp,'%f ',mwc(1,1));fprintf(fp,'%f ',mwc(1,2));fprintf(fp,'%f
',mwc(1,3));fprintf(fp,'%f\n',mwc(1,4));
fprintf(fp,'%f ',mwc(2,1));fprintf(fp,'%f ',mwc(2,2));fprintf(fp,'%f
',mwc(2,3));fprintf(fp,'%f\n',mwc(2,4));
fprintf(fp,'%f ',mwc(3,1));fprintf(fp,'%f ',mwc(3,2));fprintf(fp,'%f
',mwc(3,3));fprintf(fp,'%f\n',mwc(3,4));
fclose(fp);
mwc
mwp
out=1;
%
3D FROM M AND PHASE (out=getWorldCoordsB(ImageI,Phase00,32))
function out=getWorldCoordsB(I,yp,ithresh)
% reads in cam.txt and proj.txt and processes yp, out is XYZ of a mat5
cam=textread('cam.txt','%f');
cam=reshape(cam,[4,3]); cam=cam';
proj=textread('proj.txt','%f');
proj=reshape(proj,[4,2]);
proj=proj';
camMatrix=cam;
projMatrix=proj;
[M N]=size(yp);
d=double(camMatrix);
p=double(projMatrix);
yp=double(yp);
X=zeros(M,N);
Y=X;
Z=X;
mwc=d;
mwp=p;
for n=1:N
for m=1:M
if I(m,n)>=ithresh
xc=double(n);
yc=double(m);
c(1,1)=mwc(1,1)-mwc(3,1)*xc;
c(1,2)=mwc(1,2)-mwc(3,2)*xc;
c(1,3)=mwc(1,3)-mwc(3,3)*xc;
c(2,1)=mwc(2,1)-mwc(3,1)*yc;
c(2,2)=mwc(2,2)-mwc(3,2)*yc;
c(2,3)=mwc(2,3)-mwc(3,3)*yc;
19
c(3,1)=mwp(1,1)-mwp(2,1)*yp(m,n);
c(3,2)=mwp(1,2)-mwp(2,2)*yp(m,n);
c(3,3)=mwp(1,3)-mwp(2,3)*yp(m,n);
d(1,1)=xc-mwc(1,4);
d(2,1)=yc-mwc(2,4);
d(3,1)=yp(m,n)-mwp(1,4);
P=inv(c)*d;
X(m,n)=P(1);
Y(m,n)=P(2);
Z(m,n)=P(3);
else
X(m,n)=0;
Y(m,n)=0;
Z(m,n)=0;
end
%
if floor(Y(m,n))>22 && floor(Y(m,n))<28 && floor(X(m,n))>52 &&
floor(X(m,n))<60
%
testingthing=[X(m,n), Y(m,n), Z(m,n)]
%
end
%
%
%
if n>1000 && n<1100 && m>200 && m<300 && X(m,n)~=0
testingthing=[X(m,n), Y(m,n), Z(m,n), yp(m,n)]
end
end
end
out=zeros(M,N,3);
out(:,:,1)=X(:,:);
out(:,:,2)=Y(:,:);
out(:,:,3)=Z(:,:);
20
Download