00001
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <mexutils.h>
00015 #include <vl/hog.h>
00016
00017
00018 enum {
00019 opt_verbose, opt_variant,
00020 opt_num_orientations,
00021 opt_directed_polar_field,
00022 opt_undirected_polar_field,
00023 opt_bilinear_orientations
00024 } ;
00025
00026
00027 vlmxOption options [] = {
00028 {"Verbose", 0, opt_verbose },
00029 {"Variant", 1, opt_variant },
00030 {"NumOrientations", 1, opt_num_orientations },
00031 {"DirectedPolarField", 0, opt_directed_polar_field },
00032 {"UndirectedPolarField", 0, opt_undirected_polar_field },
00033 {"BilinearOrientations", 0, opt_bilinear_orientations },
00034 {0, 0, 0 }
00035 } ;
00036
00037 enum Mode {ExtractFeatures, Render, GetPermutation} ;
00038 enum InputType {Image, DirectedPolarField, UndirectedPolarField} ;
00039
00040 static char const * inputTypeNames [] = {
00041 "Image",
00042 "DirectedPolarField",
00043 "UndirectedPolarField"
00044 } ;
00045
00046 void
00047 mexFunction(int nout, mxArray *out[],
00048 int nin, const mxArray *in[])
00049 {
00050 mxArray const * descriptor_array ;
00051 float const * descriptor = NULL ;
00052 float const * image = NULL ;
00053 vl_size width = 0, height = 0, numChannels = 0 ;
00054 vl_size cellSize = 16 ;
00055 vl_size numOrientations = 9 ;
00056 vl_bool bilinearOrientations = VL_FALSE ;
00057 VlHogVariant variant = VlHogVariantUoctti ;
00058 char const * variantName ;
00059 enum {IN_I = 0, IN_CELLSIZE, IN_END} ;
00060 enum {OUT_FEATURES = 0} ;
00061
00062 vl_bool verbose = 0 ;
00063 int opt, next ;
00064 mxArray const *optarg ;
00065
00066 enum Mode mode = ExtractFeatures ;
00067 enum InputType inputType = Image ;
00068
00069
00070
00071
00072
00073
00074 if (nin < 1) {
00075 vlmxError(vlmxErrNotEnoughInputArguments, NULL) ;
00076 }
00077 if (nout > 1) {
00078 vlmxError(vlmxErrTooManyOutputArguments, NULL) ;
00079 }
00080
00081 if (vlmxIsString(IN(I), -1)) {
00082 mxArray const * string_array = IN(I) ;
00083 if (vlmxIsEqualToStringI(string_array, "permutation")) {
00084
00085 mode = GetPermutation ;
00086 next = 1 ;
00087
00088 } else if (vlmxIsEqualToStringI(string_array, "render")) {
00089
00090 mode = Render ;
00091 descriptor_array = IN(CELLSIZE) ;
00092 next = 2 ;
00093 if (! mxIsNumeric(descriptor_array) ||
00094 ! vlmxIsReal(descriptor_array) ||
00095 mxGetClassID(descriptor_array) != mxSINGLE_CLASS) {
00096 vlmxError(vlmxErrInvalidArgument,
00097 "DESCRIPTOR is not a real numeric array of class SINGLE.") ;
00098 }
00099 if (mxGetNumberOfDimensions(descriptor_array) > 3) {
00100 vlmxError(vlmxErrInvalidArgument,
00101 "DESCRIPTOR has more than three dimensions.") ;
00102 }
00103 if (mxGetNumberOfDimensions(descriptor_array) == 3) {
00104 numChannels = mxGetDimensions(descriptor_array)[2] ;
00105 } else {
00106 numChannels = 1 ;
00107 }
00108 descriptor = mxGetData(descriptor_array) ;
00109 height = mxGetDimensions(descriptor_array)[0] ;
00110 width = mxGetDimensions(descriptor_array)[1] ;
00111 } else {
00112 vlmxError(vlmxErrInvalidArgument,
00113 "The first argument is neither an image nor a recognized command.") ;
00114 }
00115 } else {
00116
00117 mode = ExtractFeatures ;
00118 next = 2 ;
00119 if (nin < 2) {
00120 vlmxError(vlmxErrNotEnoughInputArguments, NULL) ;
00121 }
00122 if (! mxIsNumeric(IN(I)) ||
00123 ! vlmxIsReal(IN(I)) ||
00124 mxGetClassID(IN(I)) != mxSINGLE_CLASS) {
00125 vlmxError(vlmxErrInvalidArgument,
00126 "I is not a real numeric array of class SINGLE.") ;
00127 }
00128 if (mxGetNumberOfDimensions(IN(I)) > 3) {
00129 vlmxError(vlmxErrInvalidArgument,
00130 "I has more than three dimensions.") ;
00131 }
00132 if (mxGetNumberOfDimensions(IN(I)) == 3) {
00133 numChannels = mxGetDimensions(IN(I))[2] ;
00134 } else {
00135 numChannels = 1 ;
00136 }
00137 if (! vlmxIsPlainScalar(IN(CELLSIZE))) {
00138 vlmxError(vlmxErrInvalidArgument,
00139 "CELLSIZE is not a plain scalar.") ;
00140 }
00141 if (mxGetScalar(IN(CELLSIZE)) < 1.0) {
00142 vlmxError(vlmxErrInvalidArgument,
00143 "CELLSIZE is less than 1.") ;
00144 }
00145 cellSize = (vl_size) mxGetScalar(IN(CELLSIZE)) ;
00146 image = mxGetData(IN(I)) ;
00147 height = mxGetDimensions(IN(I))[0] ;
00148 width = mxGetDimensions(IN(I))[1] ;
00149 }
00150
00151
00152 while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) {
00153 switch (opt) {
00154 case opt_variant :
00155 if (! vlmxIsString(optarg, -1)) {
00156 vlmxError(vlmxErrInvalidArgument, "VARIANT must be a string") ;
00157 }
00158 if (vlmxIsEqualToStringI(optarg, "uoctti")) {
00159 variant = VlHogVariantUoctti ;
00160 } else if (vlmxIsEqualToStringI(optarg, "dalaltriggs")) {
00161 variant = VlHogVariantDalalTriggs ;
00162 } else {
00163 vlmxError(vlmxErrInvalidArgument, "The option VARIANT has an unknown value.") ;
00164 }
00165 break ;
00166
00167 case opt_num_orientations :
00168 if (! vlmxIsPlainScalar(optarg)) {
00169 vlmxError(vlmxErrInvalidArgument, "NUMORIENTATIONS is not a plain scalar.") ;
00170 }
00171 if (mxGetScalar(optarg) < 1) {
00172 vlmxError(vlmxErrInvalidArgument, "NUMORIENTATIONS is smaller than one.") ;
00173 }
00174 numOrientations = mxGetScalar(optarg) ;
00175 break;
00176
00177 case opt_directed_polar_field :
00178 inputType = DirectedPolarField ;
00179 break ;
00180
00181 case opt_undirected_polar_field :
00182 inputType = UndirectedPolarField ;
00183 break ;
00184
00185 case opt_bilinear_orientations :
00186 bilinearOrientations = VL_TRUE ;
00187 break ;
00188
00189 case opt_verbose :
00190 ++ verbose ;
00191 break ;
00192 }
00193 }
00194
00195
00196
00197
00198
00199 switch (variant) {
00200 case VlHogVariantUoctti : variantName = "UOCTTI" ; break ;
00201 case VlHogVariantDalalTriggs : variantName = "DalalTriggs" ; break ;
00202 default: abort() ; break ;
00203 }
00204
00205 switch (mode) {
00206 case ExtractFeatures :
00207 {
00208
00209 VlHog * hog = vl_hog_new (variant, numOrientations, VL_TRUE) ;
00210 mwSize dimensions [3] ;
00211
00212 vl_hog_set_use_bilinear_orientation_assignments (hog, bilinearOrientations) ;
00213
00214 if ((inputType == DirectedPolarField ||
00215 inputType == UndirectedPolarField) &&
00216 numChannels != 2) {
00217 vlmxError(vlmxErrInvalidArgument,
00218 "NUMCHANNELS=%d is not equal to two with input of type %s.",
00219 numChannels, inputTypeNames[inputType]) ;
00220 }
00221
00222 switch (inputType) {
00223 case Image:
00224 vl_hog_put_image(hog, image, height, width, numChannels, cellSize) ;
00225 break ;
00226 case DirectedPolarField:
00227 case UndirectedPolarField:
00228 vl_hog_put_polar_field(hog, image, image + height*width,
00229 inputType == DirectedPolarField,
00230 height, width, cellSize) ;
00231 break ;
00232 default:
00233 abort() ;
00234 }
00235
00236 dimensions[0] = vl_hog_get_width(hog) ;
00237 dimensions[1] = vl_hog_get_height(hog) ;
00238 dimensions[2] = vl_hog_get_dimension(hog) ;
00239
00240 if (verbose) {
00241 mexPrintf("vl_hog: image: [%d x %d x %d]\n", height, width, numChannels) ;
00242 mexPrintf("vl_hog: descriptor: [%d x %d x %d]\n", dimensions[0], dimensions[1], dimensions[2]) ;
00243 mexPrintf("vl_hog: number of orientations: %d\n", numOrientations) ;
00244 mexPrintf("vl_hog: bilinear orientation assignments: %s\n", VL_YESNO(vl_hog_get_use_bilinear_orientation_assignments(hog))) ;
00245 mexPrintf("vl_hog: variant: %s\n", variantName) ;
00246 mexPrintf("vl_hog: input type: %s\n", inputTypeNames[inputType]) ;
00247 }
00248
00249 OUT(FEATURES) = mxCreateNumericArray(3, dimensions, mxSINGLE_CLASS, mxREAL) ;
00250 vl_hog_extract (hog, mxGetData(OUT(FEATURES))) ;
00251 vl_hog_delete(hog) ;
00252 break ;
00253 }
00254
00255 case GetPermutation :
00256 {
00257 VlHog * hog = vl_hog_new(variant, numOrientations, VL_TRUE) ;
00258 vl_size dimension = vl_hog_get_dimension(hog) ;
00259 vl_uindex k ;
00260 vl_uint32 * permutationOut ;
00261 vl_index const * permutation ;
00262
00263 if (verbose) {
00264 mexPrintf("vl_hog: number of orientations: %d\n", numOrientations) ;
00265 mexPrintf("vl_hog: variant: %s\n", variantName) ;
00266 }
00267
00268 OUT(FEATURES) = mxCreateNumericMatrix(dimension, 1, mxUINT32_CLASS, mxREAL) ;
00269 permutationOut = mxGetData(OUT(FEATURES)) ;
00270 permutation = vl_hog_get_permutation(hog) ;
00271 for (k = 0 ; k < dimension ; ++k) {
00272 permutationOut[k] = permutation[k] + 1 ;
00273 }
00274 break ;
00275 }
00276
00277 case Render :
00278 {
00279 VlHog * hog = vl_hog_new(variant, numOrientations, VL_TRUE) ;
00280 vl_size glyphSize = vl_hog_get_glyph_size(hog) ;
00281 vl_size imageHeight = glyphSize * height ;
00282 vl_size imageWidth = glyphSize * width ;
00283
00284 if (numChannels != vl_hog_get_dimension(hog)) {
00285 vlmxError(vlmxErrInvalidArgument,
00286 "The third dimension of DESCRIPTOR is not equal to the dimension of a HOG descriptor.");
00287 }
00288
00289 if (verbose) {
00290 mexPrintf("vl_hog: descriptor: [%d x %d x %d]\n", height, width, numChannels) ;
00291 mexPrintf("vl_hog: glyph image: [%d x %d]\n", imageHeight, imageWidth) ;
00292 mexPrintf("vl_hog: number of orientations: %d\n", numOrientations) ;
00293 mexPrintf("vl_hog: variant: %s\n", variantName) ;
00294 }
00295
00296 OUT(FEATURES) = mxCreateNumericMatrix(imageHeight, imageWidth, mxSINGLE_CLASS, mxREAL) ;
00297 vl_hog_render(hog,
00298 mxGetData(OUT(FEATURES)),
00299 descriptor, height, width) ;
00300 break ;
00301 }
00302 }
00303 }