/* Solve the overconstrained linear system Ma = b using a least squares error (pseudo inverse) approach. */ int solve_system (dmat M, dmat a, dmat b) /* int solve_system (M, a, b) dmat M, a, b; */ { dmat Mt,MtM,Mdag; int error; if ((M.ub1 - M.lb1) < (M.ub2 - M.lb2)) { fprintf (stderr, "solve_system: matrix M has more columns than rows\n"); return (-1); } Mt = newdmat (M.lb2, M.ub2, M.lb1, M.ub1, &error); if (error) { fprintf (stderr, "solve_system: unable to allocate matrix M_transpose\n"); return (-1); } if (transpose (M, Mt)!=0) { fprintf (stderr, "solve_system: unable to transpose matrix M\n"); return (-1); } MtM = newdmat (M.lb2, M.ub2, M.lb2, M.ub2, &error); if (error) { fprintf (stderr, "solve_system: unable to allocate matrix M_transpose_M\n"); return (-1); } if (matmul (Mt, M, MtM)!=0) { fprintf (stderr, "solve_system: unable to compute matrix product of M_transpose and M\n"); return (-1); } if (fabs (matinvert (MtM)) < 0.001) { fprintf (stderr, "solve_system: determinant of matrix M_transpose_M is too small\n"); return (-1); } /* if (errno) { fprintf (stderr, "solve_system: error during matrix inversion\n"); return (-1); } */ Mdag = newdmat (M.lb2, M.ub2, M.lb1, M.ub1, &error); if (error) { fprintf (stderr, "solve_system: unable to allocate matrix M_diag\n"); return (-1); } if (matmul (MtM, Mt, Mdag)!=0) { fprintf (stderr, "solve_system: unable to compute matrix product of M_transpose_M and M_transpose\n"); return (-1); } if (matmul (Mdag, b, a)!=0) { fprintf (stderr, "solve_system: unable to compute matrix product of M_diag and b\n"); return (-1); } freemat (Mt); freemat (MtM); freemat (Mdag); return 0; }
/* Perform the matrix multiplication c = a*b where a, b, and c are dynamic Iliffe matrices. The matrix dimensions must be commensurate. This means that c and a must have the same number of rows; c and b must have the same number of columns; and a must have the same number of columns as b has rows. The actual index origins are immaterial. If c is the same matrix as a or b, the result will be correct at the expense of more time. */ int matmul (dmat a,dmat b,dmat c) { int i, j, k, broff, croff, ccoff, /* coordinate origin offsets */ mem_alloced, error; double t; dmat d; /* temporary workspace matrix */ if (a.ub2 - a.lb2 != b.ub1 - b.lb1 || a.ub1 - a.lb1 != c.ub1 - c.lb1 || b.ub2 - b.lb2 != c.ub2 - c.lb2) { errno = EDOM; return (-1); } if (a.mat_sto != c.mat_sto && b.mat_sto != c.mat_sto) { d = c; mem_alloced = FALSE; } else { d = newdmat (c.lb1, c.ub1, c.lb2, c.ub2, &error); if (error) { fprintf (stderr, "Matmul: out of storage.\n"); errno = ENOMEM; return (-1); } mem_alloced = TRUE; } broff = b.lb1 - a.lb2; /* B's row offset from A */ croff = c.lb1 - a.lb1; /* C's row offset from A */ ccoff = c.lb2 - b.lb2; /* C's column offset from B */ for (i = a.lb1; i <= a.ub1; i++) for (j = b.lb2; j <= b.ub2; j++) { t = 0.0; for (k = a.lb2; k <= a.ub2; k++) t += a.el[i][k] * b.el[k + broff][j]; d.el[i + croff][j + ccoff] = t; } if (mem_alloced) { for (i = c.lb1; i <= c.ub1; i++) for (j = c.lb2; j <= c.ub2; j++) c.el[i][j] = d.el[i][j]; freemat (d); } return (0); }
/* Generate the transpose of a dynamic Iliffe matrix. */ int transpose (dmat A, dmat ATrans) { int i, j, rowsize, colsize, error; double **a = A.el, **atrans = ATrans.el, temp; dmat TMP; rowsize = A.ub1 - A.lb1; colsize = A.ub2 - A.lb2; if (rowsize < 0 || rowsize != ATrans.ub2 - ATrans.lb2 || colsize < 0 || colsize != ATrans.ub1 - ATrans.lb1) { errno = EDOM; return (-1); } if (A.mat_sto == ATrans.mat_sto && A.lb1 == ATrans.lb1 && A.lb2 == ATrans.lb2) { for (i = 0; i <= rowsize; i++) for (j = i + 1; j <= colsize; j++) { temp = a[A.lb1 + i][A.lb2 + j]; atrans[A.lb1 + i][A.lb2 + j] = a[A.lb1 + j][A.lb2 + i]; atrans[A.lb1 + j][A.lb2 + i] = temp; } } else if (A.mat_sto == ATrans.mat_sto) { TMP = newdmat (ATrans.lb1, ATrans.ub1, ATrans.lb2, ATrans.ub2, &error); if (error) return (-2); for (i = 0; i <= rowsize; i++) for (j = 0; j <= colsize; j++) { TMP.el[ATrans.lb1 + j][ATrans.lb2 + i] = a[A.lb1 + i][A.lb2 + j]; } matcopy (TMP, ATrans); freemat (TMP); } else { for (i = 0; i <= rowsize; i++) for (j = 0; j <= colsize; j++) atrans[ATrans.lb1 + j][ATrans.lb2 + i] = a[A.lb1 + i][A.lb2 + j]; } return (0); }
/* Solve the overconstrained linear system Ma = b using a least squares error (pseudo inverse) approach. */ int solve_system (dmat M, dmat a,dmat b) { dmat Mt, MtM, Mdag; //AfxMessageBox("S1"); if ((M.ub1 - M.lb1) < (M.ub2 - M.lb2)) { fprintf (stderr, "solve_system: matrix M has more columns than rows\n"); return (-1); } //AfxMessageBox("S2"); Mt = newdmat (M.lb2, M.ub2, M.lb1, M.ub1, &errno); if (errno) { fprintf (stderr, "solve_system: unable to allocate matrix M_transpose\n"); return (-2); } //AfxMessageBox("S3"); transpose (M, Mt); if (errno) { fprintf (stderr, "solve_system: unable to transpose matrix M\n"); return (-3); } //AfxMessageBox("S4"); MtM = newdmat (M.lb2, M.ub2, M.lb2, M.ub2, &errno); if (errno) { fprintf (stderr, "solve_system: unable to allocate matrix M_transpose_M\n"); return (-4); } //AfxMessageBox("S5"); matmul (Mt, M, MtM); if (errno) { fprintf (stderr, "solve_system: unable to compute matrix product of M_transpose and M\n"); return (-5); } //modified by Dickson //AfxMessageBox("S6"); double aa=fabs (matinvert (MtM)); //AfxMessageBox("S7"); //if (aa < 0.001) { //CString str; //str.Format("determinant=%f",aa); //AfxMessageBox("S71"); //AfxMessageBox(str); //AfxMessageBox("S8"); if (aa < 0.001) { fprintf (stderr, "solve_system: determinant of matrix M_transpose_M is too small\n"); return (-6); } if (errno) { fprintf (stderr, "solve_system: error during matrix inversion\n"); return (-7); } Mdag = newdmat (M.lb2, M.ub2, M.lb1, M.ub1, &errno); if (errno) { fprintf (stderr, "solve_system: unable to allocate matrix M_diag\n"); return (-8); } matmul (MtM, Mt, Mdag); if (errno) { fprintf (stderr, "solve_system: unable to compute matrix product of M_transpose_M and M_transpose\n"); return (-9); } matmul (Mdag, b, a); if (errno) { fprintf (stderr, "solve_system: unable to compute matrix product of M_diag and b\n"); return (-10); } freemat (Mt); freemat (MtM); freemat (Mdag); return 0; }
/******************************************************************************* Given a set of matches, compute the "best fitting" homography. matches: matching points numMatches: number of matching points h: returned homography isForward: direction of the projection (true = image1 -> image2, false = image2 -> image1) *******************************************************************************/ bool MainWindow::ComputeHomography(CMatches *matches, int numMatches, double h[3][3], bool isForward) { int error; int nEq=numMatches*2; dmat M=newdmat(0,nEq,0,7,&error); dmat a=newdmat(0,7,0,0,&error); dmat b=newdmat(0,nEq,0,0,&error); double x0, y0, x1, y1; for (int i=0;i<nEq/2;i++) { if(isForward == false) { x0 = matches[i].m_X1; y0 = matches[i].m_Y1; x1 = matches[i].m_X2; y1 = matches[i].m_Y2; } else { x0 = matches[i].m_X2; y0 = matches[i].m_Y2; x1 = matches[i].m_X1; y1 = matches[i].m_Y1; } //Eq 1 for corrpoint M.el[i*2][0]=x1; M.el[i*2][1]=y1; M.el[i*2][2]=1; M.el[i*2][3]=0; M.el[i*2][4]=0; M.el[i*2][5]=0; M.el[i*2][6]=(x1*x0*-1); M.el[i*2][7]=(y1*x0*-1); b.el[i*2][0]=x0; //Eq 2 for corrpoint M.el[i*2+1][0]=0; M.el[i*2+1][1]=0; M.el[i*2+1][2]=0; M.el[i*2+1][3]=x1; M.el[i*2+1][4]=y1; M.el[i*2+1][5]=1; M.el[i*2+1][6]=(x1*y0*-1); M.el[i*2+1][7]=(y1*y0*-1); b.el[i*2+1][0]=y0; } int ret=solve_system (M,a,b); if (ret!=0) { freemat(M); freemat(a); freemat(b); return false; } else { h[0][0]= a.el[0][0]; h[0][1]= a.el[1][0]; h[0][2]= a.el[2][0]; h[1][0]= a.el[3][0]; h[1][1]= a.el[4][0]; h[1][2]= a.el[5][0]; h[2][0]= a.el[6][0]; h[2][1]= a.el[7][0]; h[2][2]= 1; } freemat(M); freemat(a); freemat(b); return true; }