mser.c
Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00015 #define VL_MSER_DRIVER_VERSION 0.2
00016 
00017 #include "generic-driver.h"
00018 
00019 #include <vl/generic.h>
00020 #include <vl/stringop.h>
00021 #include <vl/pgm.h>
00022 #include <vl/mser.h>
00023 #include <vl/getopt_long.h>
00024 
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <assert.h>
00028 
00029 /* ----------------------------------------------------------------- */
00030 /* help message */
00031 char const help_message [] =
00032   "Usage: %s [options] files ...\n"
00033   "\n"
00034   "Options include:\n"
00035   " --verbose -v     Be verbose\n"
00036   " --help -h        Print this help message\n"
00037   " --seeds          Specify seeds file\n"
00038   " --frames         Specify frames file\n"
00039   " --meta           Specify meta file\n"
00040   " --delta -d       Specify MSER delta paramter\n"
00041   " --epsilon -e     Specify MSER epsilon parameter\n"
00042   " --no-dups        Remove duplicate\n"
00043   " --dups           Keep duplicates\n"
00044   " --max-area       Specify maximum region (relative) area\n"
00045   " --min-area       Specify minimum region (relative) area\n"
00046   " --max-variation  Specify maximum absolute region stability\n"
00047   " --bright-on-dark Enable or disable bright-on-dark regions (default 1)\n"
00048   " --dark-on-bright Enable or disable dark-on-bright regions (default 1)\n"
00049   "\n" ;
00050 
00051 /* ----------------------------------------------------------------- */
00052 /* long options codes */
00053 enum {
00054   opt_seed    = 1000,
00055   opt_frame,
00056   opt_meta,
00057   opt_max_area,
00058   opt_min_area,
00059   opt_max_variation,
00060   opt_min_diversity,
00061   opt_bright,
00062   opt_dark
00063 } ;
00064 
00065 /* short options */
00066 char const opts [] = "vhd:" ;
00067 
00068 /* long options */
00069 struct option const longopts [] = {
00070   { "verbose",         no_argument,            0,          'v'               },
00071   { "help",            no_argument,            0,          'h'               },
00072   { "delta",           required_argument,      0,          'd'               },
00073   { "seeds",           optional_argument,      0,          opt_seed          },
00074   { "frames",          optional_argument,      0,          opt_frame         },
00075   { "meta",            optional_argument,      0,          opt_meta          },
00076   { "max-area",        required_argument,      0,          opt_max_area      },
00077   { "min-area",        required_argument,      0,          opt_min_area      },
00078   { "max-variation",   required_argument,      0,          opt_max_variation },
00079   { "min-diversity",   required_argument,      0,          opt_min_diversity },
00080   { "bright-on-dark",  required_argument,      0,          opt_bright        },
00081   { "dark-on-bright",  required_argument,      0,          opt_dark          },
00082   { 0,                 0,                      0,          0                 }
00083 } ;
00084 
00085 
00086 /* ----------------------------------------------------------------- */
00089 int
00090 main(int argc, char **argv)
00091 {
00092   /* algorithm parameters */
00093   double   delta         = -1 ;
00094   double   max_area      = -1 ;
00095   double   min_area      = -1 ;
00096   double   max_variation = -1 ;
00097   double   min_diversity = -1 ;
00098   int      bright_on_dark = 1 ;
00099   int      dark_on_bright = 1 ;
00100 
00101   vl_bool  err    = VL_ERR_OK ;
00102   char     err_msg [1024] ;
00103   int      n ;
00104   int      exit_code = 0 ;
00105   int      verbose = 0 ;
00106 
00107   VlFileMeta frm  = {0, "%.frame", VL_PROT_ASCII, "", 0} ;
00108   VlFileMeta piv  = {0, "%.mser",  VL_PROT_ASCII, "", 0} ;
00109   VlFileMeta met  = {0, "%.meta",  VL_PROT_ASCII, "", 0} ;
00110 
00111 #define ERRF(msg, arg) {                                             \
00112     err = VL_ERR_BAD_ARG ;                                           \
00113     snprintf(err_msg, sizeof(err_msg), msg, arg) ;                   \
00114     break ;                                                          \
00115   }
00116 
00117 #define ERR(msg) {                                                   \
00118     err = VL_ERR_BAD_ARG ;                                           \
00119     snprintf(err_msg, sizeof(err_msg), msg) ;                        \
00120     break ;                                                          \
00121 }
00122 
00123   /* ------------------------------------------------------------------
00124    *                                                      Parse options
00125    * --------------------------------------------------------------- */
00126   while (!err) {
00127     int ch = getopt_long(argc, argv, opts, longopts, 0) ;
00128 
00129     /* If there are no files passed as input, print the help and settings */
00130     if (ch == -1 && argc - optind == 0)
00131       ch = 'h';
00132 
00133     /* end of option list? */
00134     if (ch == -1) break;
00135 
00136     /* process options */
00137     switch (ch) {
00138 
00139       /* .......................................................... */
00140     case '?' :
00141       ERRF("Invalid option '%s'.", argv [optind - 1]) ;
00142       break ;
00143 
00144     case ':' :
00145       ERRF("Missing mandatory argument for option '%s'.",
00146           argv [optind - 1]) ;
00147       break ;
00148 
00149     case 'h' :
00150       printf (help_message, argv [0]) ;
00151       printf ("MSERs  filespec: `%s'\n", piv.pattern) ;
00152       printf ("Frames filespec: `%s'\n", frm.pattern) ;
00153       printf ("Meta   filespec: `%s'\n", met.pattern) ;
00154       printf ("Version: driver %s; libvl %s\n",
00155               VL_XSTRINGIFY(VL_MSER_DRIVER_VERSION),
00156               vl_get_version_string()) ;
00157       exit (0) ;
00158       break ;
00159 
00160     case 'v' :
00161       ++ verbose ;
00162       break ;
00163 
00164       /* .......................................................... */
00165     case 'd' :
00166       n = sscanf (optarg, "%lf", &delta) ;
00167       if (n == 0 || delta < 0)
00168         ERRF("The argument of '%s' must be a non-negative number.",
00169             argv [optind - 1]) ;
00170       break ;
00171 
00172       /* ........................................................... */
00173     case opt_max_area :
00174       n = sscanf (optarg, "%lf", &max_area) ;
00175       if (n == 0 || max_area < 0 || max_area > 1)
00176         ERR("max-area argument must be in the [0,1] range.") ;
00177       break ;
00178 
00179     case opt_min_area :
00180       n = sscanf (optarg, "%lf", &min_area) ;
00181       if (n == 0 || min_area < 0 || min_area > 1)
00182         ERR("min-area argument must be in the [0,1] range.") ;
00183       break ;
00184 
00185     case opt_max_variation :
00186       n = sscanf (optarg, "%lf", &max_variation) ;
00187       if (n == 0 || max_variation < 0)
00188         ERR("max-variation argument must be non-negative.") ;
00189       break ;
00190 
00191     case opt_min_diversity :
00192       n = sscanf (optarg, "%lf", &min_diversity) ;
00193       if (n == 0 || min_diversity < 0 || min_diversity > 1)
00194         ERR("min-diversity argument must be in the [0,1] range.") ;
00195       break ;
00196 
00197       /* ........................................................... */
00198     case opt_frame :
00199       err = vl_file_meta_parse (&frm, optarg) ;
00200       if (err)
00201         ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00202       break ;
00203 
00204     case opt_seed :
00205       err = vl_file_meta_parse (&piv, optarg) ;
00206       if (err)
00207         ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00208       break ;
00209 
00210     case opt_meta :
00211       err = vl_file_meta_parse (&met, optarg) ;
00212       if (err)
00213         ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00214 
00215       if (met.protocol != VL_PROT_ASCII)
00216         ERR("meta file supports only ASCII protocol") ;
00217       break ;
00218 
00219     case opt_bright :
00220       n = sscanf (optarg, "%d", &bright_on_dark) ;
00221       if (n == 0 || (bright_on_dark != 0 && bright_on_dark != 1))
00222         ERR("bright_on_dark must be 0 or 1.") ;
00223       break ;
00224 
00225     case opt_dark :
00226       n = sscanf (optarg, "%d", &dark_on_bright) ;
00227       if (n == 0 || (dark_on_bright != 0 && dark_on_bright != 1))
00228         ERR("dark_on_bright must be 0 or 1.") ;
00229       break ;
00230 
00231       /* .......................................................... */
00232     case 0 :
00233     default :
00234       abort() ;
00235     }
00236   }
00237 
00238   /* check for parsing errors */
00239   if (err) {
00240     fprintf(stderr, "%s: error: %s (%d)\n",
00241             argv [0],
00242             err_msg, err) ;
00243     exit (1) ;
00244   }
00245 
00246   /* parse other arguments (filenames) */
00247   argc -= optind ;
00248   argv += optind ;
00249 
00250   /* make sure at least one file */
00251   if (piv.active == 0 && frm.active == 0) {
00252     frm.active = 1 ;
00253   }
00254 
00255   if (verbose > 1) {
00256     printf("mser: frames output\n") ;
00257     printf("mser:    active   %d\n",  frm.active ) ;
00258     printf("mser:    pattern  %s\n",  frm.pattern) ;
00259     printf("mser:    protocol %s\n",  vl_string_protocol_name (frm.protocol)) ;
00260     printf("mser: seeds output\n") ;
00261     printf("mser:    active   %d\n",  piv.active ) ;
00262     printf("mser:    pattern  %s\n",  piv.pattern) ;
00263     printf("mser:    protocol %s\n",  vl_string_protocol_name (piv.protocol)) ;
00264     printf("mser: meta output\n") ;
00265     printf("mser:    active   %d\n",  met.active ) ;
00266     printf("mser:    pattern  %s\n",  met.pattern) ;
00267     printf("mser:    protocol %s\n",  vl_string_protocol_name (met.protocol)) ;
00268   }
00269 
00270   /* ------------------------------------------------------------------
00271    *                                         Process one image per time
00272    * --------------------------------------------------------------- */
00273 
00274   while (argc--) {
00275 
00276     char             basename [1024] ;
00277     char const      *name = *argv++ ;
00278     VlMserFilt      *filt = 0 ;
00279     VlMserFilt      *filtinv = 0 ;
00280     vl_uint8        *data = 0 ;
00281     vl_uint8        *datainv = 0 ;
00282     VlPgmImage       pim ;
00283     vl_uint const   *regions ;
00284     vl_uint const   *regionsinv ;
00285     float const     *frames ;
00286     float const     *framesinv ;
00287     enum            {ndims = 2} ;
00288     int              dims [ndims] ;
00289     int              nregions = 0, nregionsinv = 0, nframes = 0, nframesinv =0;
00290     int              i, j, dof ;
00291     vl_size          q ;
00292     FILE            *in = 0 ;
00293 
00294     /* Open files  ------------------------------------------------ */
00295 
00296     /* get basenmae from filename */
00297     q = vl_string_basename (basename, sizeof(basename), name, 1) ;
00298     err = (q >= sizeof(basename)) ;
00299     if (err) {
00300       snprintf(err_msg, sizeof(err_msg),
00301                "Basename of '%s' is too long", name);
00302       err = VL_ERR_OVERFLOW ;
00303       goto done ;
00304     }
00305 
00306     if (verbose) {
00307       printf("mser: processing '%s'\n", name) ;
00308     }
00309 
00310     if (verbose > 1) {
00311       printf("mser:    basename is '%s'\n", basename) ;
00312     }
00313 
00314 #define WERR(name)                                              \
00315     if (err == VL_ERR_OVERFLOW) {                               \
00316       snprintf(err_msg, sizeof(err_msg),                        \
00317                "Output file name too long.") ;                  \
00318       goto done ;                                               \
00319     } else if (err) {                                           \
00320       snprintf(err_msg, sizeof(err_msg),                        \
00321                "Could not open '%s' for writing.", name) ;      \
00322       goto done ;                                               \
00323     }
00324 
00325     /* open input file */
00326     in = fopen (name, "rb") ;
00327     if (!in) {
00328       err = VL_ERR_IO ;
00329       snprintf(err_msg, sizeof(err_msg),
00330                "Could not open '%s' for reading.", name) ;
00331       goto done ;
00332     }
00333 
00334     /* open output files */
00335     err = vl_file_meta_open (&piv, basename, "w") ; WERR(piv.name) ;
00336     err = vl_file_meta_open (&frm, basename, "w") ; WERR(frm.name) ;
00337     err = vl_file_meta_open (&met, basename, "w") ; WERR(met.name) ;
00338 
00339     if (verbose > 1) {
00340       if (piv.active) printf("mser:  writing seeds  to '%s'\n", piv.name);
00341       if (frm.active) printf("mser:  writing frames to '%s'\n", frm.name);
00342       if (met.active) printf("mser:  writing meta   to '%s'\n", met.name);
00343     }
00344 
00345     /* Read image data -------------------------------------------- */
00346 
00347     /* read source image header */
00348     err = vl_pgm_extract_head (in, &pim) ;
00349     if (err) {
00350       err = VL_ERR_IO ;
00351       snprintf(err_msg, sizeof(err_msg),
00352                "PGM header corrputed.") ;
00353       goto done ;
00354     }
00355 
00356     if (verbose) {
00357       printf("mser:   image is %" VL_FMT_SIZE " by %" VL_FMT_SIZE " pixels\n",
00358              pim. width,
00359              pim. height) ;
00360     }
00361 
00362     /* allocate buffer */
00363     data = malloc(vl_pgm_get_npixels (&pim) *
00364                   vl_pgm_get_bpp       (&pim)) ;
00365 
00366     if (!data) {
00367       err = VL_ERR_ALLOC ;
00368       snprintf(err_msg, sizeof(err_msg),
00369                "Could not allocate enough memory.") ;
00370       goto done ;
00371     }
00372 
00373     /* read PGM */
00374     err  = vl_pgm_extract_data (in, &pim, data) ;
00375     if (err) {
00376       snprintf(err_msg, sizeof(err_msg),
00377                "PGM body corrputed.") ;
00378       goto done ;
00379     }
00380 
00381     /* Process data  ---------------------------------------------- */
00382     dims[0] = pim.width ;
00383     dims[1] = pim.height ;
00384 
00385     filt = vl_mser_new (ndims, dims) ;
00386     filtinv = vl_mser_new (ndims, dims) ;
00387 
00388     if (!filt || !filtinv) {
00389       snprintf(err_msg, sizeof(err_msg),
00390               "Could not create an MSER filter.") ;
00391       goto done ;
00392     }
00393 
00394     if (delta         >= 0) vl_mser_set_delta          (filt, (vl_mser_pix) delta) ;
00395     if (max_area      >= 0) vl_mser_set_max_area       (filt, max_area) ;
00396     if (min_area      >= 0) vl_mser_set_min_area       (filt, min_area) ;
00397     if (max_variation >= 0) vl_mser_set_max_variation  (filt, max_variation) ;
00398     if (min_diversity >= 0) vl_mser_set_min_diversity  (filt, min_diversity) ;
00399     if (delta         >= 0) vl_mser_set_delta          (filtinv, (vl_mser_pix) delta) ;
00400     if (max_area      >= 0) vl_mser_set_max_area       (filtinv, max_area) ;
00401     if (min_area      >= 0) vl_mser_set_min_area       (filtinv, min_area) ;
00402     if (max_variation >= 0) vl_mser_set_max_variation  (filtinv, max_variation) ;
00403     if (min_diversity >= 0) vl_mser_set_min_diversity  (filtinv, min_diversity) ;
00404 
00405 
00406     if (verbose) {
00407       printf("mser: parameters:\n") ;
00408       printf("mser:   delta         = %d\n", vl_mser_get_delta         (filt)) ;
00409       printf("mser:   max_area      = %g\n", vl_mser_get_max_area      (filt)) ;
00410       printf("mser:   min_area      = %g\n", vl_mser_get_min_area      (filt)) ;
00411       printf("mser:   max_variation = %g\n", vl_mser_get_max_variation (filt)) ;
00412       printf("mser:   min_diversity = %g\n", vl_mser_get_min_diversity (filt)) ;
00413     }
00414 
00415     if (dark_on_bright)
00416     {
00417       vl_mser_process (filt, (vl_mser_pix*) data) ;
00418 
00419       /* Save result  ----------------------------------------------- */
00420       nregions = vl_mser_get_regions_num (filt) ;
00421       regions  = vl_mser_get_regions     (filt) ;
00422 
00423       if (piv.active) {
00424         for (i = 0 ; i < nregions ; ++i) {
00425           fprintf(piv.file, "%d ", regions [i]) ;
00426         }
00427       }
00428 
00429       if (frm.active) {
00430         vl_mser_ell_fit (filt) ;
00431 
00432         nframes = vl_mser_get_ell_num (filt) ;
00433         dof     = vl_mser_get_ell_dof (filt) ;
00434         frames  = vl_mser_get_ell     (filt) ;
00435         for (i = 0 ; i < nframes ; ++i) {
00436           for (j = 0 ; j < dof ; ++j) {
00437             fprintf(frm.file, "%f ", *frames++) ;
00438           }
00439           fprintf(frm.file, "\n") ;
00440         }
00441       }
00442     }
00443     if (bright_on_dark)
00444     {
00445       /* allocate buffer */
00446       datainv = malloc(vl_pgm_get_npixels (&pim) *
00447                   vl_pgm_get_bpp       (&pim)) ;
00448       for (i = 0; i < (signed)vl_pgm_get_npixels (&pim); i++) {
00449         datainv[i] = ~data[i]; /* 255 - data[i] */
00450       }
00451 
00452       if (!datainv) {
00453         err = VL_ERR_ALLOC ;
00454         snprintf(err_msg, sizeof(err_msg),
00455                  "Could not allocate enough memory.") ;
00456         goto done ;
00457       }
00458 
00459       vl_mser_process (filtinv, (vl_mser_pix*) datainv) ;
00460 
00461       /* Save result  ----------------------------------------------- */
00462       nregionsinv = vl_mser_get_regions_num (filtinv) ;
00463       regionsinv  = vl_mser_get_regions     (filtinv) ;
00464 
00465       if (piv.active) {
00466         for (i = 0 ; i < nregionsinv ; ++i) {
00467           fprintf(piv.file, "%d ", -regionsinv [i]) ;
00468         }
00469       }
00470 
00471       if (frm.active) {
00472         vl_mser_ell_fit (filtinv) ;
00473 
00474         nframesinv = vl_mser_get_ell_num (filtinv) ;
00475         dof        = vl_mser_get_ell_dof (filtinv) ;
00476         framesinv  = vl_mser_get_ell     (filtinv) ;
00477         for (i = 0 ; i < nframesinv ; ++i) {
00478           for (j = 0 ; j < dof ; ++j) {
00479             fprintf(frm.file, "%f ", *framesinv++) ;
00480           }
00481           fprintf(frm.file, "\n") ;
00482         }
00483       }
00484     }
00485 
00486     if (met.active) {
00487       fprintf(met.file, "<mser\n") ;
00488       fprintf(met.file, "  input = '%s'\n", name) ;
00489       if (piv.active) {
00490         fprintf(met.file, "  seeds = '%s'\n", piv.name) ;
00491       }
00492       if (frm.active) {
00493         fprintf(met.file,"  frames = '%s'\n", frm.name) ;
00494       }
00495       fprintf(met.file, ">\n") ;
00496     }
00497 
00498     /* Next guy  ----------------------------------------------- */
00499   done :
00500     /* release filter */
00501     if (filt) {
00502       vl_mser_delete (filt) ;
00503       filt = 0 ;
00504     }
00505     if (filtinv) {
00506       vl_mser_delete (filtinv) ;
00507       filtinv = 0 ;
00508     }
00509 
00510     /* release image data */
00511     if (data) {
00512       free (data) ;
00513       data = 0 ;
00514     }
00515     if (datainv) {
00516       free (datainv) ;
00517       datainv = 0 ;
00518     }
00519 
00520     /* close files */
00521     if (in) {
00522       fclose (in) ;
00523       in = 0 ;
00524     }
00525 
00526     vl_file_meta_close (&frm) ;
00527     vl_file_meta_close (&piv) ;
00528     vl_file_meta_close (&met) ;
00529 
00530     /* if bad print error message */
00531     if (err) {
00532       fprintf
00533         (stderr,
00534          "mser: err: %s (%d)\n",
00535          err_msg,
00536          err) ;
00537       exit_code = 1 ;
00538     }
00539   }
00540 
00541   /* quit */
00542   return exit_code ;
00543 }


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