IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 26347


Ignore:
Timestamp:
Dec 6, 2009, 8:41:50 AM (16 years ago)
Author:
eugene
Message:

adding SVD analysis of basis function correlations

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_branches/20091201/psModules/src/imcombine/pmSubtractionEquation.c

    r26345 r26347  
    973973        }
    974974
     975# define SVD_ANALYSIS 1
    975976        // re-do this section with SVD:
    976         // psMatrixSVD ();
     977        if (SVD_ANALYSIS) {
     978            // We have sumVector and sumMatrix.  we are trying to solve the equation: sumMatrix * x = sumVector.
     979            // we can use any standard matrix inversion to solve this.  However, the basis
     980            // functions in general have substantial correlation, so that the solution may be
     981            // somewhat poorly determiend or unstable.  If not numerically ill-conditioned, the
     982            // system of equations may be statistically ill-conditioned.  Noise in the image
     983            // will drive insignificant but correlated terms in the solution.  To avoid these
     984            // problems, we can use SVD to identify numerically unconstrained values and to
     985            // avoid statistically badly determined value.
     986
     987            // A = sumMatrix, B = sumVector
     988            // SVD: A = U w V^T  -> A^{-1} = V (1/w) U^T
     989            // x = V (1/w) (U^T B)
     990            // \sigma_x = sqrt(diag(A^{-1}))
     991            // solve for x and A^{-1} to get x & dx
     992            // identify the elements of (1/w) that are nan (1/0.0) -> set to 0.0
     993            // identify the elements of x that are insignificant (x / dx < 1.0? < 0.5?) -> set to 0.0
     994
     995            // I get confused by the index values between the image vs matrix usage:  In terms
     996            // of the elements of an image A(x,y) = A->data.F32[y][x] = A_x,y, a matrix
     997            // multiplication is: A_k,j * B_i,k = C_i,j
     998
     999            psImage *U = NULL;
     1000            psImage *V = NULL;
     1001            psVector *w = NULL;
     1002            if (!psMatrixSVD (&U, &w, &V, sumMatrix)) {
     1003                psError(PS_ERR_UNKNOWN, false, "failed to perform SVD on sumMatrix\n");
     1004                return NULL;
     1005            }
     1006
     1007            // calculate A_inverse and x_svd
     1008            // A'_i,j = \sum_k (V_k,j * w_k * Ut_i,k)
     1009            // but U^T_i,j = U_j,i, so:
     1010            // A'_i,j = \sum_k (V_k,j * w_k * U_k,i)
     1011
     1012            // v1_j = \sum_k (UT_k,j * B_k)
     1013            // v1_j = w_j * \sum_k (U_j,k * B_k)
     1014            // x_i = \sum_j V_j,i * w_j * \sum_k (U_j,k * B_k)
     1015           
     1016            // A'_i,j = \sum_k (V_k,j * w_k * U_k,i)
     1017
     1018            psImage  *Ainv = psImageAlloc(A->numCols, A->numRows, PS_TYPE_F32);
     1019            psVector *Xsvd = psVectorAlloc(A->numCols, PS_TYPE_F32);
     1020            for (int iy = 0; iy < A->numRows; iy++) {
     1021                double vsum = 0.0;
     1022                for (int ix = 0; ix < A->numCols; ix++) {
     1023                    double msum = 0.0;
     1024                    double vsum1 = 0.0;
     1025                    for (int k = 0; k < A->numCols; k++) {
     1026                        if (fabs(w->data.F32[k]) < FLT_EPSILON) continue;
     1027                        msum += V->data.F32[iy][k] * U->data.F32[ix][k] / w->data.F32[k];
     1028                        vsum1 += U->data.F32[k][iy] * B->data.F32[k];
     1029                    }
     1030                    Ainv->data.F32[iy][ix] = sum;
     1031                    if (fabs(w->data.F32[ix]) < FLT_EPSILON) continue;
     1032                    vsum += V->data.F32[iy][ix] * vsum1 / w->data.F32[ix];
     1033                }
     1034                Xsvd->data.F32[iy] = vsum;
     1035            }
     1036
     1037            // compare Xsvd[k] to dXsvd and zero out w entries that are not significant
     1038            # define COEFF_SIG 1.0
     1039            for (int k = 0; k < A->numRows; k++) {
     1040                float dXsvd = sqrt(Ainv->data.F32[k][k]);
     1041                if (fabs(Xsvd->data.F32[k] / dXsvd) < COEFF_SIG) {
     1042                    w->data.F32[k] = 0.0;
     1043                }
     1044            }
     1045           
     1046            //
     1047
     1048
     1049        }
    9771050
    9781051        psVector *permutation = NULL;       // Permutation vector, required for LU decomposition
Note: See TracChangeset for help on using the changeset viewer.