void mexFunction (int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray*prhs[])

{
  int i;
  if (nrhs < 4) 
    mexErrMsgTxt("At least 4 arguments are required even nb of input arguments required.");
  else if (nlhs != 1) 
    mexErrMsgTxt("yael_fisher produces exactly 1 output argument.");

  int flags = GMM_FLAGS_MU;
  int verbose = 0;
  int fishernorm1 = 1;
  
  if(mxGetClassID(PARAM_V)!=mxSINGLE_CLASS)
    mexErrMsgTxt("need single precision array.");

  if(mxGetClassID(PARAM_W)!=mxSINGLE_CLASS)
    mexErrMsgTxt("need single precision array.");

  if(mxGetClassID(PARAM_MU)!=mxSINGLE_CLASS)
    mexErrMsgTxt("need single precision array.");

  if(mxGetClassID(PARAM_SIGMA)!=mxSINGLE_CLASS)
    mexErrMsgTxt("need single precision array.");

  float *v = (float*) mxGetPr (PARAM_V);
  float *w = (float*) mxGetPr (PARAM_W);
  float *mu = (float*) mxGetPr (PARAM_MU);
  float *sigma = (float*) mxGetPr (PARAM_SIGMA);

  {
    int i;
    for(i = 4 ; i < nrhs ; i += 1) {
      char varname[256];
      if (mxGetClassID(prhs[i]) != mxCHAR_CLASS) 
        mexErrMsgTxt ("variable name required");         

      if (mxGetString (prhs[i], varname, 256) != 0)
        mexErrMsgTxt ("Could not convert string data");

      if (!strcmp(varname, "sigma")) 
	flags |= GMM_FLAGS_SIGMA;
      
      else if (!strcmp(varname,"weights")) 
        flags |= GMM_FLAGS_W;

      else if (!strcmp(varname,"nomu")) 
        flags &= ~ GMM_FLAGS_MU;

      else if (!strcmp(varname,"verbose")) 
        verbose = 1;

      else if (!strcmp(varname,"nonorm")) 
        fishernorm1 = 0;

      else 
        mexErrMsgTxt("unknown variable name");  
    }
  }

  if (verbose) {
    fprintf (stdout, "v     -> %ld x %ld\n", mxGetM (PARAM_V), mxGetN (PARAM_V));
    fprintf (stdout, "w     -> %ld x %ld\n", mxGetM (PARAM_W), mxGetN (PARAM_W));
    fprintf (stdout, "mu    -> %ld x %ld\n", mxGetM (PARAM_MU), mxGetN (PARAM_MU));
    fprintf (stdout, "sigma -> %ld x %ld\n", mxGetM (PARAM_SIGMA), mxGetN (PARAM_SIGMA));
  }

  int d = mxGetM (PARAM_V);  /* vector dimensionality */
  int n = mxGetN (PARAM_V);  /* number of fisher vector to produce */
  int k = mxGetN (PARAM_W);  /* number of gaussian */

  if (verbose)
    fprintf (stdout, "d       = %d\nn       = %d\nk       = %d\n", d, n, k);

  if (mxGetM (PARAM_MU) != d || mxGetM (PARAM_SIGMA) != d || 
      mxGetN (PARAM_MU) !=k || mxGetN (PARAM_SIGMA) != k || 
      (mxGetM (PARAM_W) != 1 && mxGetN (PARAM_W) != 1) )
    mexErrMsgTxt("Invalid input dimensionalities.");

  

  /* ouptut: GMM, i.e., weights, mu and variances */
  gmm_t g = {d, k, w, mu, sigma};
  int dout = gmm_fisher_sizeof (&g, flags); 
  if (verbose)
    fprintf (stdout, "Size of the fisher vector = %d\n", dout);

  plhs[0] = mxCreateNumericMatrix (dout, n, mxSINGLE_CLASS, mxREAL);
  float * vf = (float *) mxGetPr (plhs[0]);
  
  #pragma omp parallel for private (i)
  for (i = 0 ; i < n ; i++) {
    gmm_fisher (1, v + i * d, &g, flags, vf + i * dout);
  }
}
示例#2
0
文件: gmm.c 项目: czxxjtu/videosearch
void gmm_fisher_save_soft_assgn(int n, const float *v, const gmm_t * g, int flags,
                                float *dp_dlambda,
                                float *word_total_soft_assignment) {
    long d=g->d, k=g->k;
    float *p = fvec_new(n * k);
    long i,j,l;
    long ii=0;

    float * vp = NULL; /* v*p */
    float * sum_pj = NULL; /* sum of p's for a given j */

    gmm_compute_p(n,v,g,p,flags | GMM_FLAGS_W);

#define P(j,i) p[(i)*k+(j)]
#define V(l,i) v[(i)*d+(l)]
#define MU(l,j) g->mu[(j)*d+(l)]
#define SIGMA(l,j) g->sigma[(j)*d+(l)]
#define VP(l,j) vp[(j)*d+(l)]

    // Save total soft assignment per centroid
    if (word_total_soft_assignment != NULL) {
        for (j=0; j<k; j++) {
            double sum=0;
            for (i=0; i<n; i++) {
                sum += P(j,i);
            }
            if (n != 0) {
                word_total_soft_assignment[j] = (float)(sum/n);
            } else {
                word_total_soft_assignment[j] = 0.0;
            }
        }
    }

    if(flags & GMM_FLAGS_W) {

        for(j=1; j<k; j++) {
            double accu=0;

            for(i=0; i<n; i++)
                accu+= P(j,i)/g->w[j] - P(0,i)/g->w[0];

            /* normalization */
            double f=n*(1/g->w[j]+1/g->w[0]);

            dp_dlambda[ii++]=accu/sqrt(f);
        }
    }

    if(flags & GMM_FLAGS_MU) {
        float *dp_dmu=dp_dlambda+ii;

#define DP_DMU(l,j) dp_dmu[(j)*d+(l)]

        if(0) { /* simple and slow */

            for(j=0; j<k; j++) {
                for(l=0; l<d; l++) {
                    double accu=0;

                    for(i=0; i<n; i++)
                        accu += P(j,i) * (V(l,i)-MU(l,j)) / SIGMA(l,j);

                    DP_DMU(l,j)=accu;
                }
            }

        } else { /* complicated and fast */

            /* precompute  tables that may be useful for sigma too */
            vp = fvec_new(k * d);
            fmat_mul_tr(v,p,d,k,n,vp);

            sum_pj = fvec_new(k);
            for(j=0; j<k; j++) {
                double sum=0;
                for(i=0; i<n; i++) sum += P(j,i);
                sum_pj[j] = sum;
            }

            for(j=0; j<k; j++) {
                for(l=0; l<d; l++)
                    DP_DMU(l,j) = (VP(l,j) - MU(l,j) * sum_pj[j]) / SIGMA(l,j);
            }

        }
        /* normalization */
        if(!(flags & GMM_FLAGS_NO_NORM)) {
            for(j=0; j<k; j++)
                for(l=0; l<d; l++) {
                    float nf = sqrt(n*g->w[j]/SIGMA(l,j));
                    if(nf > 0) DP_DMU(l,j) /= nf;
                }
        }
#undef DP_DMU
        ii+=d*k;
    }

    if(flags & (GMM_FLAGS_SIGMA | GMM_FLAGS_1SIGMA)) {


        if(flags & GMM_FLAGS_1SIGMA) { /* fast not implemented for 1 sigma */

            for(j=0; j<k; j++) {
                double accu2=0;
                for(l=0; l<d; l++) {
                    double accu=0;

                    for(i=0; i<n; i++)
                        accu += P(j,i) * (sqr(V(l,i)-MU(l,j)) / SIGMA(l,j) - 1) / sqrt(SIGMA(l,j));

                    if(flags & GMM_FLAGS_SIGMA) {

                        double f=flags & GMM_FLAGS_NO_NORM ? 1.0 : 2*n*g->w[j]/SIGMA(l,j);

                        dp_dlambda[ii++]=accu/sqrt(f);
                    }
                    accu2+=accu;
                }

                if(flags & GMM_FLAGS_1SIGMA) {
                    double f=flags & GMM_FLAGS_NO_NORM ? 1.0 : 2*d*n*g->w[j]/SIGMA(0,j);
                    dp_dlambda[ii++]=accu2/sqrt(f);
                }

            }

        } else { /* fast and complicated */
            assert(flags & GMM_FLAGS_SIGMA);
            float *dp_dsigma = dp_dlambda + ii;

            if(!vp) {
                vp = fvec_new(k * d);
                fmat_mul_tr(v,p,d,k,n,vp);
            }

            if(!sum_pj) {
                sum_pj = fvec_new(k);
                for(j=0; j<k; j++) {
                    double sum=0;
                    for(i=0; i<n; i++) sum += P(j,i);
                    sum_pj[j] = sum;
                }
            }
            float *v2 = fvec_new(n * d);
            for(i = n*d-1 ; i >= 0; i--) v2[i] = v[i] * v[i];
            float *v2p = fvec_new(k * d);
            fmat_mul_tr(v2,p,d,k,n,v2p);
            free(v2);

#define V2P(l,j) v2p[(j)*d+(l)]
#define DP_DSIGMA(i,j) dp_dsigma[(i)+(j)*d]
            for(j=0; j<k; j++) {

                for(l=0; l<d; l++) {
                    double accu;

                    accu = V2P(l, j);

                    accu += VP(l, j) * (- 2 * MU(l,j));

                    accu += sum_pj[j] * (sqr(MU(l,j))  - SIGMA(l,j));

                    /* normalization */

                    double f;

                    if(flags & GMM_FLAGS_NO_NORM) {
                        f = pow(SIGMA(l,j), -1.5);
                    } else {
                        f = 1 / (SIGMA(l,j) * sqrt(2*n*g->w[j]));
                    }

                    DP_DSIGMA(l,j) = accu * f;

                }

            }

            free(v2p);

#undef DP_DSIGMA
#undef V2P
            ii += d * k;
        }

    }

    assert(ii==gmm_fisher_sizeof(g,flags));
#undef P
#undef V
#undef MU
#undef SIGMA
    free(p);
    free(sum_pj);
    free(vp);
}