summaryrefslogtreecommitdiffstats
path: root/jni/feature_stab/db_vlvm/db_image_homography.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'jni/feature_stab/db_vlvm/db_image_homography.cpp')
-rw-r--r--jni/feature_stab/db_vlvm/db_image_homography.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/jni/feature_stab/db_vlvm/db_image_homography.cpp b/jni/feature_stab/db_vlvm/db_image_homography.cpp
new file mode 100644
index 000000000..aaad7f85e
--- /dev/null
+++ b/jni/feature_stab/db_vlvm/db_image_homography.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id: db_image_homography.cpp,v 1.2 2011/06/17 14:03:31 mbansal Exp $ */
+
+#include "db_utilities.h"
+#include "db_image_homography.h"
+#include "db_framestitching.h"
+#include "db_metrics.h"
+
+
+
+/*****************************************************************
+* Lean and mean begins here *
+*****************************************************************/
+
+/*Compute the linear constraint on H obtained by requiring that the
+ratio between coordinate i_num and i_den of xp is equal to the ratio
+between coordinate i_num and i_den of Hx. i_zero should be set to
+the coordinate not equal to i_num or i_den. No normalization is used*/
+inline void db_SProjImagePointPointConstraint(double c[9],int i_num,int i_den,int i_zero,
+ double xp[3],double x[3])
+{
+ db_MultiplyScalarCopy3(c+3*i_den,x, xp[i_num]);
+ db_MultiplyScalarCopy3(c+3*i_num,x, -xp[i_den]);
+ db_Zero3(c+3*i_zero);
+}
+
+/*Compute two constraints on H generated by the correspondence (Xp,X),
+assuming that Xp ~= H*X. No normalization is used*/
+inline void db_SProjImagePointPointConstraints(double c1[9],double c2[9],double xp[3],double x[3])
+{
+ int ma_ind;
+
+ /*Find index of coordinate of Xp with largest absolute value*/
+ ma_ind=db_MaxAbsIndex3(xp);
+
+ /*Generate 2 constraints,
+ each constraint is generated by considering the ratio between a
+ coordinate and the largest absolute value coordinate*/
+ switch(ma_ind)
+ {
+ case 0:
+ db_SProjImagePointPointConstraint(c1,1,0,2,xp,x);
+ db_SProjImagePointPointConstraint(c2,2,0,1,xp,x);
+ break;
+ case 1:
+ db_SProjImagePointPointConstraint(c1,0,1,2,xp,x);
+ db_SProjImagePointPointConstraint(c2,2,1,0,xp,x);
+ break;
+ default:
+ db_SProjImagePointPointConstraint(c1,0,2,1,xp,x);
+ db_SProjImagePointPointConstraint(c2,1,2,0,xp,x);
+ }
+}
+
+inline void db_SAffineImagePointPointConstraints(double c1[7],double c2[7],double xp[3],double x[3])
+{
+ double ct1[9],ct2[9];
+
+ db_SProjImagePointPointConstraints(ct1,ct2,xp,x);
+ db_Copy6(c1,ct1); c1[6]=ct1[8];
+ db_Copy6(c2,ct2); c2[6]=ct2[8];
+}
+
+void db_StitchProjective2D_4Points(double H[9],
+ double x1[3],double x2[3],double x3[3],double x4[3],
+ double xp1[3],double xp2[3],double xp3[3],double xp4[3])
+{
+ double c[72];
+
+ /*Collect the constraints*/
+ db_SProjImagePointPointConstraints(c ,c+9 ,xp1,x1);
+ db_SProjImagePointPointConstraints(c+18,c+27,xp2,x2);
+ db_SProjImagePointPointConstraints(c+36,c+45,xp3,x3);
+ db_SProjImagePointPointConstraints(c+54,c+63,xp4,x4);
+ /*Solve for the nullvector*/
+ db_NullVector8x9Destructive(H,c);
+}
+
+void db_StitchAffine2D_3Points(double H[9],
+ double x1[3],double x2[3],double x3[3],
+ double xp1[3],double xp2[3],double xp3[3])
+{
+ double c[42];
+
+ /*Collect the constraints*/
+ db_SAffineImagePointPointConstraints(c ,c+7 ,xp1,x1);
+ db_SAffineImagePointPointConstraints(c+14,c+21,xp2,x2);
+ db_SAffineImagePointPointConstraints(c+28,c+35,xp3,x3);
+ /*Solve for the nullvector*/
+ db_NullVector6x7Destructive(H,c);
+ db_MultiplyScalar6(H,db_SafeReciprocal(H[6]));
+ H[6]=H[7]=0; H[8]=1.0;
+}
+
+/*Compute up to three solutions for the focal length given two point correspondences
+generated by a rotation with a common unknown focal length. No specific normalization
+of the input points is required. If signed_disambiguation is true, the points are
+required to be in front of the camera*/
+inline void db_CommonFocalLengthFromRotation_2Point(double fsol[3],int *nr_sols,double x1[3],double x2[3],double xp1[3],double xp2[3],int signed_disambiguation=1)
+{
+ double m,ax,ay,apx,apy,bx,by,bpx,bpy;
+ double p1[2],p2[2],p3[2],p4[2],p5[2],p6[2];
+ double p7[3],p8[4],p9[5],p10[3],p11[4];
+ double roots[3];
+ int nr_roots,i,j;
+
+ /*Solve for focal length using the equation
+ <a,b>^2*<ap,ap><bp,bp>=<ap,bp>^2*<a,a><b,b>
+ where a and ap are the homogenous vectors in the first image
+ after focal length scaling and b,bp are the vectors in the
+ second image*/
+
+ /*Normalize homogenous coordinates so that last coordinate is one*/
+ m=db_SafeReciprocal(x1[2]);
+ ax=x1[0]*m;
+ ay=x1[1]*m;
+ m=db_SafeReciprocal(xp1[2]);
+ apx=xp1[0]*m;
+ apy=xp1[1]*m;
+ m=db_SafeReciprocal(x2[2]);
+ bx=x2[0]*m;
+ by=x2[1]*m;
+ m=db_SafeReciprocal(xp2[2]);
+ bpx=xp2[0]*m;
+ bpy=xp2[1]*m;
+
+ /*Compute cubic in l=1/(f^2)
+ by dividing out the root l=0 from the equation
+ (l(ax*bx+ay*by)+1)^2*(l(apx^2+apy^2)+1)*(l(bpx^2+bpy^2)+1)=
+ (l(apx*bpx+apy*bpy)+1)^2*(l(ax^2+ay^2)+1)*(l(bx^2+by^2)+1)*/
+ p1[1]=ax*bx+ay*by;
+ p2[1]=db_sqr(apx)+db_sqr(apy);
+ p3[1]=db_sqr(bpx)+db_sqr(bpy);
+ p4[1]=apx*bpx+apy*bpy;
+ p5[1]=db_sqr(ax)+db_sqr(ay);
+ p6[1]=db_sqr(bx)+db_sqr(by);
+ p1[0]=p2[0]=p3[0]=p4[0]=p5[0]=p6[0]=1;
+
+ db_MultiplyPoly1_1(p7,p1,p1);
+ db_MultiplyPoly1_2(p8,p2,p7);
+ db_MultiplyPoly1_3(p9,p3,p8);
+
+ db_MultiplyPoly1_1(p10,p4,p4);
+ db_MultiplyPoly1_2(p11,p5,p10);
+ db_SubtractPolyProduct1_3(p9,p6,p11);
+ /*Cubic starts at p9[1]*/
+ db_SolveCubic(roots,&nr_roots,p9[4],p9[3],p9[2],p9[1]);
+
+ for(j=0,i=0;i<nr_roots;i++)
+ {
+ if(roots[i]>0)
+ {
+ if((!signed_disambiguation) || (db_PolyEval1(p1,roots[i])*db_PolyEval1(p4,roots[i])>0))
+ {
+ fsol[j++]=db_SafeSqrtReciprocal(roots[i]);
+ }
+ }
+ }
+ *nr_sols=j;
+}
+
+int db_StitchRotationCommonFocalLength_3Points(double H[9],double x1[3],double x2[3],double x3[3],double xp1[3],double xp2[3],double xp3[3],double *f,int signed_disambiguation)
+{
+ double fsol[3];
+ int nr_sols,i,best_sol,done;
+ double cost,best_cost;
+ double m,hyp[27],x1_temp[3],x2_temp[3],xp1_temp[3],xp2_temp[3];
+ double *hyp_point,ft;
+ double y[2];
+
+ db_CommonFocalLengthFromRotation_2Point(fsol,&nr_sols,x1,x2,xp1,xp2,signed_disambiguation);
+ if(nr_sols)
+ {
+ db_DeHomogenizeImagePoint(y,xp3);
+ done=0;
+ for(i=0;i<nr_sols;i++)
+ {
+ ft=fsol[i];
+ m=db_SafeReciprocal(ft);
+ x1_temp[0]=x1[0]*m;
+ x1_temp[1]=x1[1]*m;
+ x1_temp[2]=x1[2];
+ x2_temp[0]=x2[0]*m;
+ x2_temp[1]=x2[1]*m;
+ x2_temp[2]=x2[2];
+ xp1_temp[0]=xp1[0]*m;
+ xp1_temp[1]=xp1[1]*m;
+ xp1_temp[2]=xp1[2];
+ xp2_temp[0]=xp2[0]*m;
+ xp2_temp[1]=xp2[1]*m;
+ xp2_temp[2]=xp2[2];
+
+ hyp_point=hyp+9*i;
+ db_StitchCameraRotation_2Points(hyp_point,x1_temp,x2_temp,xp1_temp,xp2_temp);
+ hyp_point[2]*=ft;
+ hyp_point[5]*=ft;
+ hyp_point[6]*=m;
+ hyp_point[7]*=m;
+ cost=db_SquaredReprojectionErrorHomography(y,hyp_point,x3);
+
+ if(!done || cost<best_cost)
+ {
+ done=1;
+ best_cost=cost;
+ best_sol=i;
+ }
+ }
+
+ if(f) *f=fsol[best_sol];
+ db_Copy9(H,hyp+9*best_sol);
+ return(1);
+ }
+ else
+ {
+ db_Identity3x3(H);
+ if(f) *f=1.0;
+ return(0);
+ }
+}
+
+void db_StitchSimilarity2DRaw(double *scale,double R[4],double t[2],
+ double **Xp,double **X,int nr_points,int orientation_preserving,
+ int allow_scaling,int allow_rotation,int allow_translation)
+{
+ int i;
+ double c[2],cp[2],r[2],rp[2],M[4],s,sp,sc;
+ double *temp,*temp_p;
+ double Aacc,Bacc,Aacc2,Bacc2,divisor,divisor2,m,Am,Bm;
+
+ if(allow_translation)
+ {
+ db_PointCentroid2D(c,X,nr_points);
+ db_PointCentroid2D(cp,Xp,nr_points);
+ }
+ else
+ {
+ db_Zero2(c);
+ db_Zero2(cp);
+ }
+
+ db_Zero4(M);
+ s=sp=0;
+ for(i=0;i<nr_points;i++)
+ {
+ temp= *X++;
+ temp_p= *Xp++;
+ r[0]=(*temp++)-c[0];
+ r[1]=(*temp++)-c[1];
+ rp[0]=(*temp_p++)-cp[0];
+ rp[1]=(*temp_p++)-cp[1];
+
+ M[0]+=r[0]*rp[0];
+ M[1]+=r[0]*rp[1];
+ M[2]+=r[1]*rp[0];
+ M[3]+=r[1]*rp[1];
+
+ s+=db_sqr(r[0])+db_sqr(r[1]);
+ sp+=db_sqr(rp[0])+db_sqr(rp[1]);
+ }
+
+ /*Compute scale*/
+ if(allow_scaling) sc=sqrt(db_SafeDivision(sp,s));
+ else sc=1.0;
+ *scale=sc;
+
+ /*Compute rotation*/
+ if(allow_rotation)
+ {
+ /*orientation preserving*/
+ Aacc=M[0]+M[3];
+ Bacc=M[2]-M[1];
+ /*orientation reversing*/
+ Aacc2=M[0]-M[3];
+ Bacc2=M[2]+M[1];
+ if(Aacc!=0.0 || Bacc!=0.0)
+ {
+ divisor=sqrt(Aacc*Aacc+Bacc*Bacc);
+ m=db_SafeReciprocal(divisor);
+ Am=Aacc*m;
+ Bm=Bacc*m;
+ R[0]= Am;
+ R[1]= Bm;
+ R[2]= -Bm;
+ R[3]= Am;
+ }
+ else
+ {
+ db_Identity2x2(R);
+ divisor=0.0;
+ }
+ if(!orientation_preserving && (Aacc2!=0.0 || Bacc2!=0.0))
+ {
+ divisor2=sqrt(Aacc2*Aacc2+Bacc2*Bacc2);
+ if(divisor2>divisor)
+ {
+ m=db_SafeReciprocal(divisor2);
+ Am=Aacc2*m;
+ Bm=Bacc2*m;
+ R[0]= Am;
+ R[1]= Bm;
+ R[2]= Bm;
+ R[3]= -Am;
+ }
+ }
+ }
+ else db_Identity2x2(R);
+
+ /*Compute translation*/
+ if(allow_translation)
+ {
+ t[0]=cp[0]-sc*(R[0]*c[0]+R[1]*c[1]);
+ t[1]=cp[1]-sc*(R[2]*c[0]+R[3]*c[1]);
+ }
+ else db_Zero2(t);
+}
+
+