=====The Homography model==== =====Compute an image given an original image and the homography between the 2 image planes===== function imout=CalculeImageHomographie(H,imout,hautout,largout,imin,hautin,largin) %fonction imout=CalculeImageHomographie(H,imout,hautout,largout,imin,hautin,largin) %@Bertrand VANDEPORTAELE %La fonction calcule l'image imout à partir de l'image imin %H= homographie entre les 2 images tel que imout= H*imin %imout= image de sortie, elle est aussi en entrée, car on peut la modifier %hautout,largout= dimensions de l'image de sortie %imin= image d'entrée %hautin,largin= dimensions de l'image d'entrée %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% for y=1:hautout for x=1:largout p2=H*[x,y,1]'; %transformation homographique inverse ud=round(p2(1)/p2(3)); vd=round(p2(2)/p2(3)); ud; vd; if vd>0 & ud>0 & vd<=hautin & ud<=largin %ca tombe dans l'image val=imin(vd,ud); imout(y,x)=val; %on attribue la couleur du pixel concerné else %ca tombe hors de l'image datamatrix, on laisse la valeur du %fond %eventuellement, on aurait pu faire: % imout(y,x)=255; %on attribue la couleur blanche end end end =====Estimation of Homography from 2D points correspondances using the DLT algorithm===== function [ H] = compute2DHomographyUsingDLT( p1,p2) %B. Vandeportaele %compute the Homography H using the DLT Algorithm for 4 2D points %correspondences such as : p2=H.p1 u11=p1(1,1);u12=p1(1,2); u13=p1(1,3);u14=p1(1,4); v11=p1(2,1);v12=p1(2,2); v13=p1(2,3);v14=p1(2,4); u21=p2(1,1);u22=p2(1,2); u23=p2(1,3);u24=p2(1,4); v21=p2(2,1);v22=p2(2,2); v23=p2(2,3);v24=p2(2,4); A=[ -u11, -v11, -1, 0, 0, 0, u11*u21, u21*v11; 0, 0, 0, -u11, -v11, -1, u11*v21, v21*v11; -u12, -v12, -1, 0, 0, 0, u12*u22, u22*v12; 0, 0, 0, -u12, -v12, -1, u12*v22, v22*v12; -u13, -v13, -1, 0, 0, 0, u13*u23, u23*v13; 0, 0, 0, -u13, -v13, -1, u13*v23, v23*v13; -u14, -v14, -1, 0, 0, 0, u14*u24, u24*v14; 0, 0, 0, -u14, -v14, -1, u14*v24, v24*v14]; B =[ -u21; -v21; -u22; -v22; -u23; -v23; -u24; -v24]; %solve A*Hv=B Hv=inv(A)*B; %reconstruct the homography matrix from the vector solution H=[Hv(1:3)';Hv(4:6)';Hv(7:8)',1]; end ====Checking the obtained results==== function [ err] = check2DHomography(H, p1,p2 ) %B. Vandeportaele %compute the error in R2 (after deshomogeneisation) for every points %contained in p1 and p2 matrices considering the homography H %err= p2 -deshomogenieisation(H.p1) err=[]; for i=1:size(p1,2) u11=p1(1,i); v11=p1(2,i); wuv21p=H*[u11;v11;1]; err(1,i)=p2(1,i)-(wuv21p(1)/wuv21p(3)); err(2,i)=p2(2,i)-(wuv21p(2)/wuv21p(3)); end end ====Normalization of the data for least squares fitting==== function [ p2, s,tx,ty] = normalizeForH( p1 ) %B. Vandeportaele %normalization of the data for homography estimation. Scale s and %translation (tx,ty) is computed to obtain a distribution of point with 0 %mean and sqrt(2) std dev. %as explained in Geometry in Computer Vision (2ed,OUP,2003)(T)(672s) % Data Normalization p107 & p180 %transform p1 points to p2 such that p2 points are centered around 0:0 and mean distance to 0:0 is sqrt(2) %eventually see page 128 for the case where some points in p1 are very far away from the origin %it would require a complete homography instead of just a scaling and %translation, as it involve dealing with p1 in projective space P2 %in page 109, it is explained that non isotropic scaling is not necessary. %average distance m=mean(p1,2)'; %p1-[m(1)*ones(1,size(p1,2)); m(2)*ones(1,size(p1,2))] %translation to bring the centroid at 0:0 dist=[]; for i=1:size(p1,2) pc(1:2,i)=p1(:,i)-m'; %centered points dist(i)=norm(pc(1:2,i),2); end meandist=mean(dist) s=sqrt(2)/meandist; for i=1:size(p1,2) p2(1:2,i)=s*pc(:,i); %scaled and centered points end tx=-s*m(1); ty=-s*m(2); end =====Uncertainty propagation===== %B. Vandeportaele %script to achieve symbolic computation of the jacobian % du2/dHij % dv2/dHij % Hij being the coefficients of the homography such as % w.u2 u1 % w.v2 = H . v1 % w. 1 clear all param=1 h11=sym('h11','real');h12=sym('h12','real');h13=sym('h13','real'); h21=sym('h21','real');h22=sym('h22','real');h23=sym('h23','real'); h31=sym('h31','real');h32=sym('h32','real');h33=sym('h33','real'); %possibly use 2 parameterization for the homography, h33 may be set to 1 if param==0 H=[h11 h12 h13; h21 h22 h23;h31 h32 h33] else H=[h11 h12 h13; h21 h22 h23;h31 h32 1] end u1=sym('u1','real'); v1=sym('v1','real'); P1=[u1;v1;1]; %apply the homography P2=H*P1 %deshomogeneization u2=P2(1,:)/P2(3,:) v2=P2(2,:)/P2(3,:) %compute the jacobians if param==0 J=jacobian ([u2, v2], [h11, h12, h13, h21, h22, h23, h31, h32, h33]) else J=jacobian ([u2, v2], [h11, h12, h13, h21, h22, h23, h31, h32]) end Conclusion for param=1: $J= \left(\begin{array}{cccccccc} \frac{\mathrm{u1}}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & \frac{\mathrm{v1}}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & 0 & 0 & 0 & -\frac{\mathrm{u1}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u1} + \mathrm{h12}\, \mathrm{v1}\right)}{{\left(\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1\right)}^2} & -\frac{\mathrm{v1}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u1} + \mathrm{h12}\, \mathrm{v1}\right)}{{\left(\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1\right)}^2}\\ 0 & 0 & 0 & \frac{\mathrm{u1}}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & \frac{\mathrm{v1}}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1} & -\frac{\mathrm{u1}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u1} + \mathrm{h22}\, \mathrm{v1}\right)}{{\left(\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1\right)}^2} & -\frac{\mathrm{v1}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u1} + \mathrm{h22}\, \mathrm{v1}\right)}{{\left(\mathrm{h31}\, \mathrm{u1} + \mathrm{h32}\, \mathrm{v1} + 1\right)}^2} \end{array}\right)$ %B. Vandeportaele %script to illustrate uncertainty propagation for homography (projective %transformation) clear all %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %define 4 set of 2 2D points correspondances such as % w.u21 u11 % w.v21 = H . v11 % w. 1 % position u11,v11 in plane 1 is supposed to be perfectly known u11=0;v11=0; u12=1;v12=0; u13=0;v13=1; u14=1;v14=1; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %position u21,v21 in plane 2 is associated with a covariance matrix u21=10;v21=10; u22=150;v22=40; u23=30;v23=130; u24=190;v24=210; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %covariance for the point's positions in plane 2. std dev are square roots %of the diagonal values %default value: Cp=1*eye(8) %change the value as needed if uncertainty are not the same for all the %points if 1 Cp(1,1)=3; Cp(2,2)=5; Cp(3,3)=10; Cp(4,4)=25; Cp(5,5)=50; Cp(6,6)=1; Cp(7,7)=0.1; Cp(8,8)=0.1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %store coordinates in matrices p1=[u11,u12,u13,u14;v11,v12,v13,v14] p2=[u21,u22,u23,u24;v21,v22,v23,v24] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %DLT Algorithm: [ H] = compute2DHomographyUsingDLT( p1,p2) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %check computed H, should be 0 [ err] = check2DHomography(H, p1,p2 ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% h11=H(1,1);h12=H(1,2);h13=H(1,3); h21=H(2,1);h22=H(2,2);h23=H(2,3); h31=H(3,1);h32=H(3,2);h33=H(3,3); %compute J numerically then invert the 8x8 matrix to obtain Ji J =[]; % computed in jaco.m: J=jacobian ([u2, v2], [h11, h12, h13, h21, h22, h23, h31, h32]) for i=1:4 u1=p1(1,i);v1=p1(2,i); J=[J; u1/(h31*u1 + h32*v1 + 1), v1/(h31*u1 + h32*v1 + 1), 1/(h31*u1 + h32*v1 + 1), 0, 0, 0, -(u1*(h13 + h11*u1 + h12*v1))/(h31*u1 + h32*v1 + 1)^2, -(v1*(h13 + h11*u1 + h12*v1))/(h31*u1 + h32*v1 + 1)^2; 0, 0, 0, u1/(h31*u1 + h32*v1 + 1), v1/(h31*u1 + h32*v1 + 1), 1/(h31*u1 + h32*v1 + 1), -(u1*(h23 + h21*u1 + h22*v1))/(h31*u1 + h32*v1 + 1)^2, -(v1*(h23 + h21*u1 + h22*v1))/(h31*u1 + h32*v1 + 1)^2]; end J detJ=det(J) %check if detJ is high enough, otherwise it won't be invertible in %practice if detJ<0.01 display 'the system looks ill-conditionned' return; end Ji=inv(J) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % In case we want to estimate H from more than 4 correspondances, get from: % http://stackoverflow.com/questions/30737382/getting-covariance-matrix-when-using-levenberg-marquardt-lsqcurvefit-in-matlab % I think I have solved this myself but will post how here if anyone else is having the same trouble. % The covariance matrix can be calculated from the Jacobian by: % C = inv(J'*J)*MSE % Where MSE is mean-square error: % MSE = (R'*R)/(N-p) % Where R = residuals, N = number of observations, p = number of coefficients estimated. % Or MSE can be calculated via iteration. % Hopefully this will help someone else in the future. % If anyone spots error please let me know. Thanks %QUESTION????? in that case what is the inverse of the (non square) jacobian for the inverse homography H^-1 %propagation of thee covariance to the coefficients of H Ch=Ji*Cp*Ji' detCh=det(Ch) %what is the meaning of that value: look at %https://math.stackexchange.com/questions/889425/what-does-determinant-of-covariance-matrix-give %compute the covariance on the coefficients of the 2D points, it should give %the same value than Cp Cp2=J*Ch*J' ErrorCp=Cp-Cp2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %Plot the uncertainty on a grid sampled in plane 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% close all figure hold on axis equal for u15=-2:.25:2; for v15=-2:.25:2; wuv25=H*[u15;v15;1]; u25=wuv25(1)/wuv25(3); v25=wuv25(2)/wuv25(3); Jp=[ u15/(h31*u15 + h32*v15 + 1), v15/(h31*u15 + h32*v15 + 1), 1/(h31*u15 + h32*v15 + 1), 0, 0, 0, -(u15*(h13 + h11*u15 + h12*v15))/(h31*u15 + h32*v15 + 1)^2, -(v15*(h13 + h11*u15 + h12*v15))/(h31*u15 + h32*v15 + 1)^2; 0, 0, 0, u15/(h31*u15 + h32*v15 + 1), v15/(h31*u15 + h32*v15 + 1), 1/(h31*u15 + h32*v15 + 1), -(u15*(h23 + h21*u15 + h22*v15))/(h31*u15 + h32*v15 + 1)^2, -(v15*(h23 + h21*u15 + h22*v15))/(h31*u15 + h32*v15 + 1)^2]; Cp5=Jp*Ch*Jp'; plotcovar(u25,v25,Cp5,'r+','b-'); end end %plot the covariance for the four 2D point correspondances used by DLT for i=1:4 u2=p2(1,i);v2=p2(2,i); Cpi=Cp(1+(i-1)*2:2+(i-1)*2,1+(i-1)*2:2+(i-1)*2); plotcovar(u2,v2,Cpi,'g+','g-'); end %en vert, 4 points (et leur incertitude) utilisés pour estimer l'homographie par Direct Linear Transform %en rouge, des points auquel on applique l'homographie calculée (interpolation et extrapolation) %et en bleu l'incertitude de l'homographie estimé propagée à ces points ====Function to plot the covariance==== function plotcovar(u,v,C,m1,m2) %get from http://www.visiondummy.com/2014/04/draw-error-ellipse-representing-covariance-matrix/ % Get the 95% confidence interval error ellipse chisquare_val = 2.4477; %INFO: pour une covariance=identité, trace un cercle de RAYON chisquare_val %pour une covariance diagonale, les termes de variance sont les carrés des écarts type %l'ellipse tracée un aura ses DEMI-axes de longeur ecart type * chisquare_val %hold on %plotcovar(10,20,[2,4;3,1],'r+','b-'); %plotcovar(10,20,[1,0;0,1],'r+','b-'); plot(u,v,m1) %bvdp, added step to inforce that C is symetric %if this precaution is not taken, this kind of matrix can be provided %C=[0.999999999999951 2.73114864057789e-14;-1.50990331349021e-14 0.999999999999964] %and it will result in complex eigen value, which won't be treatable by the %atan2 function used later... Cm=(C(2,1)+C(1,2))/2; C(2,1)=Cm; C(1,2)=Cm; % Calculate the eigenvectors and eigenvalues covariance =C; [eigenvec, eigenval ] = eig(covariance); [eigenvec, eigenval ] = eig(covariance,'nobalance'); % Get the index of the largest eigenvector [largest_eigenvec_ind_c, r] = find(eigenval == max(max(eigenval))); largest_eigenvec = eigenvec(:, largest_eigenvec_ind_c); % Get the largest eigenvalue largest_eigenval = max(max(eigenval)); % Get the smallest eigenvector and eigenvalue if(largest_eigenvec_ind_c == 1) smallest_eigenval = max(eigenval(:,2)); smallest_eigenvec = eigenvec(:,2); else smallest_eigenval = max(eigenval(:,1)); smallest_eigenvec = eigenvec(1,:); end % Calculate the angle scriptshellbetween the x-axis and the largest eigenvector angle = atan2(largest_eigenvec(2), largest_eigenvec(1)); % This angle is between -pi and pi. % Let's shift it such that the angle is between 0 and 2pi if(angle < 0) angle = angle + 2*pi; end % Get the coordinates of the data mean avg = [u;v]; %mean(data); theta_grid = linspace(0,2*pi); phi = angle; X0=avg(1); Y0=avg(2); a=chisquare_val*sqrt(largest_eigenval); b=chisquare_val*sqrt(smallest_eigenval); % the ellipse in x and y coordinates ellipse_x_r = a*cos( theta_grid ); ellipse_y_r = b*sin( theta_grid ); %Define a rotation matrix R = [ cos(phi) sin(phi); -sin(phi) cos(phi) ]; %let's rotate the ellipse to some angle phi r_ellipse = [ellipse_x_r;ellipse_y_r]' * R; % Draw the error ellipse plot(r_ellipse(:,1) + X0,r_ellipse(:,2) + Y0,m2) %hold on; % Plot the original data %plot(data(:,1), data(:,2), '.'); %mindata = min(min(data)); %maxdata = max(max(data)); %Xlim([mindata-3, maxdata+3]); %Ylim([mindata-3, maxdata+3]); %hold on; % Plot the eigenvectors %quiver(X0, Y0, largest_eigenvec(1)*sqrt(largest_eigenval), largest_eigenvec(2)*sqrt(largest_eigenval), '-m', 'LineWidth',2); %quiver(X0, Y0, smallest_eigenvec(1)*sqrt(smallest_eigenval), smallest_eigenvec(2)*sqrt(smallest_eigenval), '-g', 'LineWidth',2); %hold on; % Set the axis labels %hXLabel = xlabel('x'); %hYLabel = ylabel('y'); ====Results==== {{https://bvdp.inetdoc.net/files/homography/homographyuncertainty.png}} =====Bi-cubic interpolation of Homographies===== function val = bilinearInterpolationMulti(x, y, A) %B. Vandeportaele [haut,larg,nbchannels]=size(A); %preallocate the return value val=zeros(nbchannels,1); u=x; v=y; fu= floor(x); fv = floor(y); A1=(fv+1-v)*(fu+1-u); A2=(fv+1-v)*(u-fu); A3=(v-fv)*(fu+1-u); A4=(v-fv)*(u-fu); %if ( (fu>=0) && (fu=0) && (fv=1) && (fu=1) && (fv function val = bicubicInterpolationMulti(x, y, data) %B. Vandeportaele %https://en.wikipedia.org/wiki/Bicubic_interpolation %https://fr.wikipedia.org/wiki/Interpolation_bicubique %A is a k.l.m matrix, m being the number of channels nbchannels=size(data,3); %preallocate the return value val=zeros(nbchannels,1); %Control points x0 = floor(x); y0 = floor(y); x_1 = x0-1; x1 = x0+1; x2 = x0+2; y_1 = y0-1; y1 = y0+1; y2 = y0+2; for n=1:nbchannels % Function evaluated at control points f_1_1 = data(y_1,x_1,n); f_10 = data(y0,x_1,n); f_11 = data(y1,x_1,n); f_12 = data(y2,x_1,n); f0_1 = data(y_1,x0,n); f00 = data(y0,x0,n); f01 = data(y1, x0,n); f02 = data(y2, x0,n); f1_1 = data(y_1, x1,n); f10 = data(y0, x1,n); f11 = data(y1, x1,n); f12 = data(y2, x1,n); f2_1 = data(y_1, x2,n); f20 = data(y0, x2,n); f21 = data(y1, x2,n); f22 = data(y2, x2,n); % Derivatives in x evaluated at control points fx0_1 = (f1_1 - f_1_1)/2; fx00 = (f10 - f_10)/2; fx01 = (f11 - f_11)/2; fx02 = (f12 - f_12)/2; fx1_1 = (f2_1 - f0_1)/2; fx10 = (f20 - f00)/2; fx11 = (f21 - f01)/2; fx12 = (f22 - f02)/2; % Derivatives in y evaluated at control points fy00 = (f01 - f0_1)/2; fy10 = (f11 - f1_1)/2; fy01 = (f02 - f00)/2; fy11 = (f12 - f10)/2; % Derivatives in x and y evaluated at control points fxy00 = (fx01 - fx0_1)/2; fxy10 = (fx11 - fx1_1)/2; fxy01 = (fx02 - fx00)/2; fxy11 = (fx12 - fx10)/2; % Interpolation Px=[1,(x-x0),(x-x0)^2,(x-x0)^3]; %don't know why but sometime the generated Px is a column vector Px=reshape(Px,1,4); Py=[1;(y-y0);(y-y0)^2;(y-y0)^3]; A=[ 1 0 0 0; ... Coefficients aij 0 0 1 0; ... -3 3 -2 -1; ... 2 -2 1 1]; F=[ f00 f01 fy00 fy01; ... f10 f11 fy10 fy11; ... fx00 fx01 fxy00 fxy01; ... fx10 fx11 fxy10 fxy11]; val(n)=Px*A*F*A'*Py; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % saveRawFloat save a matlab matrix to a binary file for export. % Input : - mat : matrix to export in a binary file. % - nomfichier : file name of the futur binary file. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% function saveRawFloat(mat, nomfichier) %saveRawFloat(zeros(4), '../tmp/test.raw') % Compute number of values, we want to save nb=1; for i=1:size(size(mat),2) nb=nb*size(mat,i); end % Open the file fid = fopen(nomfichier, 'wb'); % Save the number of elements fwrite(fid, nb, 'uint32'); % il faudra verifier l'endianess... % Transpose matrix to save data line after line. % Data are saved in simple precision floating point numbers 32 bits. fwrite(fid, mat', 'float'); fclose (fid); %B. Vandeportaele October 2017 %Cubic spline interpolation in Homography space for deflectometry close all clear all %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %set the size of the spline control point grid sx=15; sy=10; %how many sampled pixels between 2 control points in each direction for %the generation of the image samplingfactor=100; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %choose the type of interpolation for homography coefficients through %function pointer InterpolationFunction=@bicubicInterpolationMulti; %InterpolationFunction=@bilinearInterpolationMulti; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% HomographyGrid=zeros(sy,sx,9); %identity matrix by default HomographyDefault=reshape(eye(3),9,1); %if the default value has to be set differently %HomographyDefault=reshape([1,0,65; 0,1,0; 0,0,1],9,1); %fill the grid with the default value for y=1:sy for x=1:sx HomographyGrid(y,x,:)=HomographyDefault; end end %perturbate some control points of the spline HomographyGrid(5,4,:)=reshape([1,0,0; 0,1,0; 0,0,0.9],9,1); HomographyGrid(4,4,:)=reshape([1.3,0,0; 0,1.3,0; 0,0,1],9,1); % HomographyGrid(5,4,:)=reshape([1,0,0; 0,1,0; 0,0,0.22],9,1); % HomographyGrid(5,5,:)=reshape([1,0,0; 0,1,0; 0,0,1.3],9,1); % HomographyGrid(6,5,:)=reshape([1,0,0; 0,1,0; 0,0,1.5],9,1); % HomographyGrid(6,4,:)=reshape([1,0,0; 0,1,0; 0,0,0.3],9,1); % HomographyGrid(6,4,:)=reshape([1.2,0,0; 0,0.9,0; 0,0,1],9,1); HomographyGrid(6,5,:)=reshape([1,0,0; 0,1,0; 0,0,1],9,1); HomographyGrid(6,8,:)=reshape([1,0,60; 0,1,-30; 0,0,1],9,1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %interpolate the homography in a small region at low resolution for %visualization purpose %very unefficient code because the size of the destination matrix are not %known at the begining=> reallocation indy=1; for yy=3:0.1:sy-2 indx=1; for xx=3:0.1:sx-2 %val = InterpolationFunction( xx,yy,HomographyGrid); val = feval(InterpolationFunction, xx,yy,HomographyGrid); indx=indx+1; res(indy,indx,1)=xx; res(indy,indx,2)=yy; res(indy,indx,3)=val(9); InterpolatedFunction(indy,indx,:)=val; end indy=indy+1; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure axis equal plot3(res(:,:,1),res(:,:,2),res(:,:,3),'r+') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% figure for channel=1:9 subplot(3,3,channel) imagesc(InterpolatedFunction(:,:,channel)) end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %compute correspondance map correspondancemapu=zeros(sy*samplingfactor,sx*samplingfactor); correspondancemapv=zeros(sy*samplingfactor,sx*samplingfactor); for yy=2*samplingfactor:sy*samplingfactor-3*samplingfactor for xx=2*samplingfactor:sx*samplingfactor-3*samplingfactor %if xx==1099 % display 'ici' %end H =reshape( InterpolationFunction( xx/samplingfactor,yy/samplingfactor,HomographyGrid),3,3); p2=H*[xx,yy,1]'; %transformation homographique inverse %ud=round(p2(1)/p2(3)); %vd=round(p2(2)/p2(3)); ud=p2(1)/p2(3); vd=p2(2)/p2(3); correspondancemapu(yy,xx)=ud; correspondancemapv(yy,xx)=vd; end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %save to a correspondance map using an openCV compatible format %file saved with .map extension map=[correspondancemapv;correspondancemapu]; imagedirectory='./'; mapname=sprintf('%s/correspondance.map',imagedirectory); saveRawFloat(map, mapname); display('correspondance.map file saved in imagedirectory'); %future use: process the images using python bindings of opencv remap %function: see /media/HD500GO/saveHDDgarossos/menage_ocamcalib/remap %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Apply the interpolated homography to a synthetic image. %%% it visualizes the equivalent of the control grid but in the source %%% image plane imoutsinu=zeros(sy*samplingfactor,sx*samplingfactor); imoutsinv=zeros(sy*samplingfactor,sx*samplingfactor); imoutsinuv=zeros(sy*samplingfactor,sx*samplingfactor); imoutsinvu=zeros(sy*samplingfactor,sx*samplingfactor); imoutcircle=zeros(sy*samplingfactor,sx*samplingfactor); imoutradial=zeros(sy*samplingfactor,sx*samplingfactor); imoutgrid=zeros(sy*samplingfactor,sx*samplingfactor); for yy=2*samplingfactor:size(imoutsinu,1)-3*samplingfactor for xx=2*samplingfactor:size(imoutsinu,2)-3*samplingfactor ud=correspondancemapu(yy,xx); vd=correspondancemapv(yy,xx); %for a square grid valpix=127*mod(floor(ud/samplingfactor),2) + 127*mod(floor(vd/samplingfactor),2) ; imoutgrid(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in u direction valpix=uint8(127+127*sin(ud/2.5)); imoutsinu(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in v direction valpix=uint8(127+127*sin(vd/2.5)); imoutsinv(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in uv diagonal direction valpix=uint8(127+127*sin((vd+ud)/(2*2.5))); imoutsinuv(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in vu diagonal direction valpix=uint8(127+127*sin((vd-ud)/(2*2.5))); imoutsinvu(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in circle direction valpix=uint8(127+127*sin((norm([(ud-750);(vd-500)],2) /2.5))); imoutcircle(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in radial direction angle=atan2((vd-500),(ud-750))*20; valpix=uint8(127+127*sin(angle)); imoutradial(yy,xx)=valpix; %on attribue la couleur du pixel concerné end end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %display images figure subplot(3,1,1); image(imoutgrid); axis equal;colormap(gray(256)); subplot(3,1,2); image(imoutsinu); axis equal;colormap(gray(256)); subplot(3,1,3); image(imoutsinv); axis equal;colormap(gray(256)); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %save images imwrite(uint8(imoutgrid),'imoutgrid.png'); imwrite(uint8(imoutsinu),'imoutu.png'); imwrite(uint8(imoutsinv),'imoutv.png'); imwrite(uint8(imoutsinuv),'imoutuv.png'); imwrite(uint8(imoutsinvu),'imoutvu.png'); imwrite(uint8(imoutcircle),'imoutcircle.png'); imwrite(uint8(imoutradial),'imoutradial.png'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %generate sequences of images nn=0; for angle=0:2*pi/60:2*pi if angle~=0 nn=nn+1 end for yy=2*samplingfactor:size(imoutsinu,1)-3*samplingfactor for xx=2*samplingfactor:size(imoutsinu,2)-3*samplingfactor ud=correspondancemapu(yy,xx); vd=correspondancemapv(yy,xx); %for a sinus wave in u direction valpix=uint8(127+127*sin(angle+(ud/2.5))); imoutsinu(yy,xx)=valpix; %on attribue la couleur du pixel concerné %for a sinus wave in v direction valpix=uint8(127+127*sin(angle+(vd/2.5))); imoutsinv(yy,xx)=valpix; %on attribue la couleur du pixel concerné end end imgname=sprintf('%s/sinu%02i.png',imagedirectory,nn); imwrite(uint8(imoutsinu),imgname); imgname=sprintf('%s/sinv%02i.png',imagedirectory,nn); imwrite(uint8(imoutsinv),imgname); end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %compute the mpg videos... does not work from within matlab, invoke it %through a linux shell %system('avconv -f image2 -i sinu%02d.png -f avi -vcodec mpeg4 -b 4000k -g 300 -bf 2 -y ./videosinu.mpg') %system('avconv -f image2 -i sinv%02d.png -f avi -vcodec mpeg4 -b 4000k -g 300 -bf 2 -y ./videosinv.mpg'); ====Results==== {{https://bvdp.inetdoc.net/files/deflectometry/imoutu.png}} {{https://bvdp.inetdoc.net/files/deflectometry/imoutv.png}} =====Garbage===== $\left(\begin{array}{ccc} {\mathrm{q1}}^2 + {\mathrm{q2}}^2 - {\mathrm{q3}}^2 - {\mathrm{q4}}^2 & 2\, \mathrm{q2}\, \mathrm{q3} - 2\, \mathrm{q1}\, \mathrm{q4} & 2\, \mathrm{q1}\, \mathrm{q3} + 2\, \mathrm{q2}\, \mathrm{q4}\\ 2\, \mathrm{q1}\, \mathrm{q4} + 2\, \mathrm{q2}\, \mathrm{q3} & {\mathrm{q1}}^2 - {\mathrm{q2}}^2 + {\mathrm{q3}}^2 - {\mathrm{q4}}^2 & 2\, \mathrm{q3}\, \mathrm{q4} - 2\, \mathrm{q1}\, \mathrm{q2}\\ 2\, \mathrm{q2}\, \mathrm{q4} - 2\, \mathrm{q1}\, \mathrm{q3} & 2\, \mathrm{q1}\, \mathrm{q2} + 2\, \mathrm{q3}\, \mathrm{q4} & {\mathrm{q1}}^2 - {\mathrm{q2}}^2 - {\mathrm{q3}}^2 + {\mathrm{q4}}^2 \end{array}\right) $ $\left(\begin{array}{ccccccccccc} 2\, \mathrm{q1} & 2\, \mathrm{q2} & - 2\, \mathrm{q3} & - 2\, \mathrm{q4} & -\frac{\mathrm{nx}}{d} & 0 & 0 & -\frac{\mathrm{tx}}{d} & 0 & 0 & \frac{\mathrm{nx}\, \mathrm{tx}}{d^2}\\ - 2\, \mathrm{q4} & 2\, \mathrm{q3} & 2\, \mathrm{q2} & - 2\, \mathrm{q1} & -\frac{\mathrm{ny}}{d} & 0 & 0 & 0 & -\frac{\mathrm{tx}}{d} & 0 & \frac{\mathrm{ny}\, \mathrm{tx}}{d^2}\\ 2\, \mathrm{q3} & 2\, \mathrm{q4} & 2\, \mathrm{q1} & 2\, \mathrm{q2} & -\frac{\mathrm{nz}}{d} & 0 & 0 & 0 & 0 & -\frac{\mathrm{tx}}{d} & \frac{\mathrm{nz}\, \mathrm{tx}}{d^2}\\ 2\, \mathrm{q4} & 2\, \mathrm{q3} & 2\, \mathrm{q2} & 2\, \mathrm{q1} & 0 & -\frac{\mathrm{nx}}{d} & 0 & -\frac{\mathrm{ty}}{d} & 0 & 0 & \frac{\mathrm{nx}\, \mathrm{ty}}{d^2}\\ 2\, \mathrm{q1} & - 2\, \mathrm{q2} & 2\, \mathrm{q3} & - 2\, \mathrm{q4} & 0 & -\frac{\mathrm{ny}}{d} & 0 & 0 & -\frac{\mathrm{ty}}{d} & 0 & \frac{\mathrm{ny}\, \mathrm{ty}}{d^2}\\ - 2\, \mathrm{q2} & - 2\, \mathrm{q1} & 2\, \mathrm{q4} & 2\, \mathrm{q3} & 0 & -\frac{\mathrm{nz}}{d} & 0 & 0 & 0 & -\frac{\mathrm{ty}}{d} & \frac{\mathrm{nz}\, \mathrm{ty}}{d^2}\\ - 2\, \mathrm{q3} & 2\, \mathrm{q4} & - 2\, \mathrm{q1} & 2\, \mathrm{q2} & 0 & 0 & -\frac{\mathrm{nx}}{d} & -\frac{\mathrm{tz}}{d} & 0 & 0 & \frac{\mathrm{nx}\, \mathrm{tz}}{d^2}\\ 2\, \mathrm{q2} & 2\, \mathrm{q1} & 2\, \mathrm{q4} & 2\, \mathrm{q3} & 0 & 0 & -\frac{\mathrm{ny}}{d} & 0 & -\frac{\mathrm{tz}}{d} & 0 & \frac{\mathrm{ny}\, \mathrm{tz}}{d^2}\\ 2\, \mathrm{q1} & - 2\, \mathrm{q2} & - 2\, \mathrm{q3} & 2\, \mathrm{q4} & 0 & 0 & -\frac{\mathrm{nz}}{d} & 0 & 0 & -\frac{\mathrm{tz}}{d} & \frac{\mathrm{nz}\, \mathrm{tz}}{d^2} \end{array}\right)$ $\left(\begin{array}{cccccccc} \frac{u_{1}1}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & \frac{\mathrm{v11}}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & \frac{1}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & 0 & 0 & 0 & -\frac{u_{1}1\, \left(\mathrm{h13} + \mathrm{h11}\, u_{1}1 + \mathrm{h12}\, \mathrm{v11}\right)}{{\left(\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1\right)}^2} & -\frac{\mathrm{v11}\, \left(\mathrm{h13} + \mathrm{h11}\, u_{1}1 + \mathrm{h12}\, \mathrm{v11}\right)}{{\left(\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1\right)}^2}\\ 0 & 0 & 0 & \frac{u_{1}1}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & \frac{\mathrm{v11}}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & \frac{1}{\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1} & -\frac{u_{1}1\, \left(\mathrm{h23} + \mathrm{h21}\, u_{1}1 + \mathrm{h22}\, \mathrm{v11}\right)}{{\left(\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1\right)}^2} & -\frac{\mathrm{v11}\, \left(\mathrm{h23} + \mathrm{h21}\, u_{1}1 + \mathrm{h22}\, \mathrm{v11}\right)}{{\left(\mathrm{h31}\, u_{1}1 + \mathrm{h32}\, \mathrm{v11} + 1\right)}^2}\\ \frac{\mathrm{u12}}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & \frac{\mathrm{v12}}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & 0 & 0 & 0 & -\frac{\mathrm{u12}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u12} + \mathrm{h12}\, \mathrm{v12}\right)}{{\left(\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1\right)}^2} & -\frac{\mathrm{v12}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u12} + \mathrm{h12}\, \mathrm{v12}\right)}{{\left(\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1\right)}^2}\\ 0 & 0 & 0 & \frac{\mathrm{u12}}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & \frac{\mathrm{v12}}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1} & -\frac{\mathrm{u12}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u12} + \mathrm{h22}\, \mathrm{v12}\right)}{{\left(\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1\right)}^2} & -\frac{\mathrm{v12}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u12} + \mathrm{h22}\, \mathrm{v12}\right)}{{\left(\mathrm{h31}\, \mathrm{u12} + \mathrm{h32}\, \mathrm{v12} + 1\right)}^2}\\ \frac{\mathrm{u13}}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & \frac{\mathrm{v13}}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & 0 & 0 & 0 & -\frac{\mathrm{u13}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u13} + \mathrm{h12}\, \mathrm{v13}\right)}{{\left(\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1\right)}^2} & -\frac{\mathrm{v13}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u13} + \mathrm{h12}\, \mathrm{v13}\right)}{{\left(\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1\right)}^2}\\ 0 & 0 & 0 & \frac{\mathrm{u13}}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & \frac{\mathrm{v13}}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1} & -\frac{\mathrm{u13}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u13} + \mathrm{h22}\, \mathrm{v13}\right)}{{\left(\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1\right)}^2} & -\frac{\mathrm{v13}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u13} + \mathrm{h22}\, \mathrm{v13}\right)}{{\left(\mathrm{h31}\, \mathrm{u13} + \mathrm{h32}\, \mathrm{v13} + 1\right)}^2}\\ \frac{\mathrm{u14}}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & \frac{\mathrm{v14}}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & 0 & 0 & 0 & -\frac{\mathrm{u14}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u14} + \mathrm{h12}\, \mathrm{v14}\right)}{{\left(\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1\right)}^2} & -\frac{\mathrm{v14}\, \left(\mathrm{h13} + \mathrm{h11}\, \mathrm{u14} + \mathrm{h12}\, \mathrm{v14}\right)}{{\left(\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1\right)}^2}\\ 0 & 0 & 0 & \frac{\mathrm{u14}}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & \frac{\mathrm{v14}}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & \frac{1}{\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1} & -\frac{\mathrm{u14}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u14} + \mathrm{h22}\, \mathrm{v14}\right)}{{\left(\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1\right)}^2} & -\frac{\mathrm{v14}\, \left(\mathrm{h23} + \mathrm{h21}\, \mathrm{u14} + \mathrm{h22}\, \mathrm{v14}\right)}{{\left(\mathrm{h31}\, \mathrm{u14} + \mathrm{h32}\, \mathrm{v14} + 1\right)}^2} \end{array}\right)$ $\left(\begin{array}{c} \frac{\mathrm{fx}\, x + \mathrm{pu}\, z}{z} - \frac{\mathrm{fx}\, x - \mathrm{bp} + \mathrm{pu}\, z}{z}\\ 0 \end{array}\right)$ =====BSPLINES===== $\left(\begin{array}{ccccccccc} - \frac{u^3}{6} + \frac{u^2}{2} - \frac{u}{2} + \frac{1}{6} & 0 & \frac{u^3}{2} - u^2 + \frac{2}{3} & 0 & - \frac{u^3}{2} + \frac{u^2}{2} + \frac{u}{2} + \frac{1}{6} & 0 & \frac{u^3}{6} & 0 & - \left(\mathrm{p1x} - \mathrm{p2x}\right)\, \left( - u^2 + u + \frac{1}{2}\right) - \left(\mathrm{p0x} - \mathrm{p1x}\right)\, \left(\frac{u^2}{2} - u + \frac{1}{2}\right) - \frac{u^2\, \left(\mathrm{p2x} - \mathrm{p3x}\right)}{2}\\ 0 & - \frac{u^3}{6} + \frac{u^2}{2} - \frac{u}{2} + \frac{1}{6} & 0 & \frac{u^3}{2} - u^2 + \frac{2}{3} & 0 & - \frac{u^3}{2} + \frac{u^2}{2} + \frac{u}{2} + \frac{1}{6} & 0 & \frac{u^3}{6} & - \left(\mathrm{p1y} - \mathrm{p2y}\right)\, \left( - u^2 + u + \frac{1}{2}\right) - \left(\mathrm{p0y} - \mathrm{p1y}\right)\, \left(\frac{u^2}{2} - u + \frac{1}{2}\right) - \frac{u^2\, \left(\mathrm{p2y} - \mathrm{p3y}\right)}{2} \end{array}\right)$