vl_erfill.c
Go to the documentation of this file.
00001 /* file:        erfill.mex.c
00002 ** description: Extremal Regions filling
00003 ** author:      Andrea Vedaldi
00004 **/
00005 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
00012 */
00013 
00018 #include <mexutils.h>
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <math.h>
00023 #include <string.h>
00024 #include <assert.h>
00025 
00026 #define MIN(x,y) (((x)<(y))?(x):(y))
00027 #define MAX(x,y) (((x)>(y))?(x):(y))
00028 
00029 typedef char unsigned val_t ;
00030 typedef int           idx_t ;
00031 typedef vl_uint64 acc_t ;
00032 
00033 /* advance N-dimensional subscript */
00034 void
00035 adv(mwSize const* dims, int ndims, int* subs_pt)
00036 {
00037   int d = 0 ;
00038   while(d < ndims) {
00039     if( ++subs_pt[d]  < (signed) dims[d] ) return ;
00040     subs_pt[d++] = 0 ;
00041   }
00042 }
00043 
00044 /* driver */
00045 void
00046 mexFunction(int nout, mxArray *out[],
00047             int nin, const mxArray *in[])
00048 {
00049 
00050   enum {IN_I=0, IN_ER} ;
00051   enum {OUT_MEMBERS} ;
00052 
00053   idx_t i ;
00054   int k, nel, ndims ;
00055   mwSize const * dims ;
00056   val_t const * I_pt ;
00057   int last = 0 ;
00058   int last_expanded = 0 ;
00059   val_t value = 0 ;
00060 
00061   double const * er_pt ;
00062 
00063   int*   subs_pt ;       /* N-dimensional subscript                 */
00064   int*   nsubs_pt ;      /* diff-subscript to point to neigh.       */
00065   idx_t* strides_pt ;    /* strides to move in image array          */
00066   val_t* visited_pt ;    /* flag                                    */
00067   idx_t* members_pt ;    /* region members                          */
00068   bool invert = VL_FALSE ;
00069 
00073   if (nin != 2) {
00074     mexErrMsgTxt("Two arguments required.") ;
00075   } else if (nout > 4) {
00076     mexErrMsgTxt("Too many output arguments.");
00077   }
00078 
00079   if(mxGetClassID(in[IN_I]) != mxUINT8_CLASS) {
00080     mexErrMsgTxt("I must be of class UINT8.") ;
00081   }
00082 
00083   if(!vlmxIsPlainScalar(in[IN_ER])) {
00084     mexErrMsgTxt("ER must be a DOUBLE scalar.") ;
00085   }
00086 
00087   /* get dimensions */
00088   nel   = mxGetNumberOfElements(in[IN_I]) ;
00089   ndims = mxGetNumberOfDimensions(in[IN_I]) ;
00090   dims  = mxGetDimensions(in[IN_I]) ;
00091   I_pt  = mxGetData(in[IN_I]) ;
00092 
00093   /* allocate stuff */
00094   subs_pt    = mxMalloc( sizeof(int)      * ndims ) ;
00095   nsubs_pt   = mxMalloc( sizeof(int)      * ndims ) ;
00096   strides_pt = mxMalloc( sizeof(idx_t)    * ndims ) ;
00097   visited_pt = mxMalloc( sizeof(val_t)    * nel   ) ;
00098   members_pt = mxMalloc( sizeof(idx_t)    * nel   ) ;
00099 
00100   er_pt = mxGetPr(in[IN_ER]) ;
00101 
00102   /* compute strides to move into the N-dimensional image array */
00103   strides_pt [0] = 1 ;
00104   for(k = 1 ; k < ndims ; ++k) {
00105     strides_pt [k] = strides_pt [k-1] * dims [k-1] ;
00106   }
00107 
00108   /* load first pixel */
00109   memset(visited_pt, 0, sizeof(val_t) * nel) ;
00110   {
00111     idx_t idx = (idx_t) *er_pt ;
00112     if (idx < 0) {
00113       idx = -idx;
00114       invert = VL_TRUE ;
00115     }
00116     if( idx < 1 || idx > nel ) {
00117       char buff[80] ;
00118       snprintf(buff,80,"ER=%d out of range [1,%d]",idx,nel) ;
00119       mexErrMsgTxt(buff) ;
00120     }
00121     members_pt [last++] = idx - 1 ;
00122   }
00123   value = I_pt[ members_pt[0] ]  ;
00124 
00125   /* -----------------------------------------------------------------
00126    *                                                       Fill region
00127    * -------------------------------------------------------------- */
00128   while(last_expanded < last) {
00129 
00130     /* pop next node xi */
00131     idx_t index = members_pt[last_expanded++] ;
00132 
00133     /* convert index into a subscript sub; also initialize nsubs
00134        to (-1,-1,...,-1) */
00135     {
00136       idx_t temp = index ;
00137       for(k = ndims-1 ; k >=0 ; --k) {
00138         nsubs_pt [k] = -1 ;
00139         subs_pt  [k] = temp / strides_pt [k] ;
00140         temp         = temp % strides_pt [k] ;
00141       }
00142     }
00143 
00144     /* process neighbors of xi */
00145     while(VL_TRUE) {
00146       int good = VL_TRUE ;
00147       idx_t nindex = 0 ;
00148 
00149       /* compute NSUBS+SUB, the correspoinding neighbor index NINDEX
00150          and check that the pixel is within image boundaries. */
00151       for(k = 0 ; k < ndims && good ; ++k) {
00152         int temp = nsubs_pt [k] + subs_pt [k] ;
00153         good &= 0 <= temp && temp < (signed) dims[k] ;
00154         nindex += temp * strides_pt [k] ;
00155       }
00156 
00157       /* process neighbor
00158          1 - the pixel is within image boundaries;
00159          2 - the pixel is indeed different from the current node
00160          (this happens when nsub=(0,0,...,0));
00161          3 - the pixel has value not greather than val
00162          is a pixel older than xi
00163          4 - the pixel has not been visited yet
00164       */
00165       if(good
00166          && nindex != index
00167          && ((!invert && I_pt [nindex] <= value) ||
00168              ( invert && I_pt [nindex] >= value))
00169          && ! visited_pt [nindex] ) {
00170 
00171         /* mark as visited */
00172         visited_pt [nindex] = 1 ;
00173 
00174         /* add to list */
00175         members_pt [last++] = nindex ;
00176       }
00177 
00178       /* move to next neighbor */
00179       k = 0 ;
00180       while(++ nsubs_pt [k] > 1) {
00181         nsubs_pt [k++] = -1 ;
00182         if(k == ndims) goto done_all_neighbors ;
00183       }
00184     } /* next neighbor */
00185   done_all_neighbors : ;
00186   } /* goto pop next member */
00187 
00188   /*
00189    * Save results
00190    */
00191   {
00192     mwSize dims[2] ;
00193     int unsigned * pt ;
00194     dims[0] = last ;
00195     out[OUT_MEMBERS] = mxCreateNumericArray(1,dims,mxUINT32_CLASS,mxREAL);
00196     pt = mxGetData(out[OUT_MEMBERS]) ;
00197     for (i = 0 ; i < last ; ++i) {
00198       *pt++ = members_pt[i] + 1 ;
00199     }
00200   }
00201 
00202   /* free stuff */
00203   mxFree( members_pt ) ;
00204   mxFree( visited_pt ) ;
00205   mxFree( strides_pt ) ;
00206   mxFree( nsubs_pt   ) ;
00207   mxFree( subs_pt    ) ;
00208 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51