00001
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <mexutils.h>
00017 #include <vl/mathop.h>
00018 #include <vl/aib.h>
00019
00020 #include <assert.h>
00021 #include <string.h>
00022
00023
00024 enum {
00025 opt_cluster_null = 0,
00026 opt_verbose
00027 } ;
00028
00029
00030 vlmxOption options [] = {
00031 {"ClusterNull",0, opt_cluster_null},
00032 {"Verbose", 0, opt_verbose },
00033 {0, 0, 0 }
00034 } ;
00035
00036 #define CLUSTER_NULL_NODES 1
00037
00051 static void
00052 cluster_null_nodes (vl_uint32* parents, vl_uint32 nvalues, double *cost, int verbosity)
00053 {
00054 vl_uint32 nnull = 0 ;
00055 vl_uint32 n ;
00056 vl_uint32 first ;
00057 vl_uint32 last_intermed ;
00058
00059 vl_uint32 a, b, c, d, e ;
00060 vl_uint32 dp, ep ;
00061
00062
00063 for (n = 0 ; n < nvalues ; ++ n) {
00064 if (parents[n] >= 2 * nvalues - 1) {
00065 ++ nnull ;
00066 }
00067 }
00068
00069 if (nnull == 0) return ;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 a = nvalues ;
00092 b = nvalues + nnull - 1 - 1 ;
00093 c = b + 1 ;
00094 d = c + 1 ;
00095 e = 2 * nvalues - 2 ;
00096
00097 dp = nvalues ;
00098 ep = 2 * nvalues - 2 - nnull ;
00099
00100 if (verbosity > 1) {
00101 mexPrintf("vl_aib: a:%u b:%u c:%u d:%u e:%u dp:%u ep:%u\n",
00102 a,b,c,d,e,dp,ep) ;
00103 }
00104
00105
00106 {
00107 vl_uint32 first_parent = e ;
00108 first = 0 ;
00109 for (n = 0 ; n < nvalues ; ++ n) {
00110 if ((parents[n] <= e) & (parents[n] != 1)) {
00111 if (first_parent >= parents [n]) {
00112 first_parent = parents [n] ;
00113 first = n ;
00114 }
00115 }
00116 }
00117 }
00118
00119 if (verbosity > 1) {
00120 mexPrintf("vl_aib: nnull:%u, nvalues:%u, first: %u\n",
00121 nnull,nvalues,first) ;
00122 }
00123
00124
00125 for (n = 0 ; n < e ; ++ n) {
00126 if ((parents [n] <= e) & (parents [n] != 0)) {
00127 parents [n] += (e - ep) ;
00128 }
00129 }
00130 for (n = e ; n >= d ; -- n) {
00131 parents [n] = parents [n - (e - ep)] ;
00132 }
00133
00134
00135 last_intermed = a ;
00136 for (n = 0 ; n < a ; ++ n) {
00137 if (parents[n] > e) {
00138 parents [n] = last_intermed ;
00139 break ;
00140 }
00141 }
00142
00143 if (verbosity > 1) {
00144 mexPrintf("vl_aib:first null %u parent seto to last_intermed:%u\n",
00145 n,
00146 last_intermed) ;
00147 }
00148
00149
00150 for (; n < a ; ++ n) {
00151 if (parents[n] > e) {
00152 parents [n] = last_intermed ;
00153 parents [last_intermed] = last_intermed + 1 ;
00154 ++ last_intermed ;
00155 }
00156 }
00157
00158 if (verbosity > 1) {
00159 mexPrintf("vl_aib: after chaining other nulls last_intermed:%u\n", last_intermed) ;
00160 }
00161
00162
00163 parents [last_intermed] = d ;
00164
00165
00166 if (verbosity > 1) {
00167 mexPrintf("vl_aib: parent of %u (first) was %u\n", first, parents[first]) ;
00168 }
00169 parents [first] = last_intermed ;
00170 if (verbosity > 1) {
00171 mexPrintf("vl_aib: parent of %u (first) is now %u\n", first, parents[first]) ;
00172 }
00173
00174
00175
00176 if (cost) {
00177 cost -= nvalues - 1 ;
00178 for (n = e ; n >= d ; --n) {
00179 cost [n] = cost [n - (e - ep)] ;
00180 }
00181 for (n = c ; n >= a ; --n) {
00182 cost [n] = cost [d] ;
00183 }
00184 }
00185 }
00186
00191 void
00192 mexFunction(int nout, mxArray *out[],
00193 int nin, const mxArray *in[])
00194 {
00195 enum {IN_PCX = 0, IN_END} ;
00196 enum {OUT_PARENTS = 0, OUT_COST} ;
00197 enum {INFORMATION, EC} ;
00198
00199 int verbose = 0 ;
00200 int opt ;
00201 int next = IN_END ;
00202 mxArray const *optarg ;
00203 int cluster_null = 0 ;
00204
00205 double *Pcx ;
00206 vl_uint32 nlabels ;
00207 vl_uint32 nvalues ;
00208
00209 mxArray *Pcx_cpy ;
00210
00211 VL_USE_MATLAB_ENV ;
00212
00213
00214
00215
00216
00217 if (nin < 1) {
00218 mexErrMsgTxt("One argument required.") ;
00219 } else if (nout > 2) {
00220 mexErrMsgTxt("Too many output arguments.");
00221 }
00222
00223 if (!vlmxIsMatrix(in[IN_PCX], -1, -1)) {
00224 mexErrMsgTxt("PCX must be a real matrix.") ;
00225 }
00226
00227 Pcx_cpy = mxDuplicateArray(in[IN_PCX]);
00228 Pcx = mxGetPr (Pcx_cpy) ;
00229 nlabels = mxGetM (in[IN_PCX]) ;
00230 nvalues = mxGetN (in[IN_PCX]) ;
00231
00232 while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00233
00234 switch (opt) {
00235
00236 case opt_verbose :
00237 ++ verbose ;
00238 break ;
00239
00240 case opt_cluster_null :
00241 cluster_null = 1 ;
00242 break ;
00243
00244 }
00245 }
00246
00247 if (verbose) {
00248 mexPrintf("vl_aib: clustering null probability variables: %s\n", VL_YESNO(cluster_null)) ;
00249 }
00250
00251
00252
00253
00254
00255 {
00256 VlAIB *aib;
00257 double* acost = 0, *cost = 0 ;
00258 vl_uint32 *aparents = 0, *parents = 0 ;
00259 vl_uint32 n ;
00260
00261 out[OUT_PARENTS] = mxCreateNumericMatrix(1, 2*nvalues - 1, mxUINT32_CLASS, mxREAL);
00262 parents = mxGetData(out[OUT_PARENTS]);
00263
00264 if (nout > 1) {
00265 out[OUT_COST] = mxCreateNumericMatrix(1, nvalues, mxDOUBLE_CLASS, mxREAL);
00266 cost = mxGetPr(out[OUT_COST]);
00267 }
00268
00269 aib = vl_aib_new (Pcx, nvalues, nlabels) ;
00270 vl_aib_set_verbosity (aib, verbose) ;
00271 vl_aib_process (aib);
00272
00273 aparents = vl_aib_get_parents (aib);
00274 acost = vl_aib_get_costs (aib);
00275 memcpy(parents, aparents, sizeof(vl_uint32)*(2*nvalues-1));
00276 if (nout > 1)
00277 memcpy(cost, acost, sizeof(double)*nvalues);
00278
00279 vl_aib_delete(aib);
00280
00281 if (cluster_null) {
00282 cluster_null_nodes (parents, nvalues, (nout == 0) ? 0 : cost, verbose) ;
00283 }
00284
00285
00286 for (n = 0 ; n < 2 * nvalues - 1 ; ++n) {
00287 if (parents [n] > 2 * nvalues - 1) {
00288
00289 parents [n] = 0 ;
00290 } else {
00291
00292 ++ parents [n] ;
00293 }
00294 }
00295
00296 }
00297 mxDestroyArray(Pcx_cpy);
00298 }