From e3451158e9e1d0d2cb1f81197a8e392ac4294ec0 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Thu, 8 Nov 2007 17:04:45 +0000 Subject: [PATCH] Custom image resizing mindtct appears to completely ignore the pixels-per-mm input parameter (ippmm). When processing AES4000 images, the binarized image is completely mangled and a lot of ridge information is lost. Resizing the AES4000's small images results in a huge imaging performance gain. We use imagemagick for the resizing, as it's resizing code resamples the image too (smoothing it out), which further improves performance. --- configure.ac | 4 +++ libfprint/Makefile.am | 4 +-- libfprint/drivers/aes4000.c | 1 + libfprint/fp_internal.h | 1 + libfprint/img.c | 61 ++++++++++++++++++++++++++++++++++++- 5 files changed, 68 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index e6b501a..55f342a 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,10 @@ PKG_CHECK_MODULES(GLIB, "glib-2.0") AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) +PKG_CHECK_MODULES(IMAGEMAGICK, "ImageMagick") +AC_SUBST(IMAGEMAGICK_CFLAGS) +AC_SUBST(IMAGEMAGICK_LIBS) + # Examples build AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build], [build example applications (default n)])], diff --git a/libfprint/Makefile.am b/libfprint/Makefile.am index ea07a41..18c0c52 100644 --- a/libfprint/Makefile.am +++ b/libfprint/Makefile.am @@ -43,9 +43,9 @@ NBIS_SRC = \ nbis/mindtct/sort.c \ nbis/mindtct/util.c -libfprint_la_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(AM_CFLAGS) +libfprint_la_CFLAGS = -fvisibility=hidden -I$(srcdir)/nbis/include $(LIBUSB_CFLAGS) $(GLIB_CFLAGS) $(IMAGEMAGICK_CFLAGS) $(AM_CFLAGS) libfprint_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@ -libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) +libfprint_la_LIBADD = -lm $(LIBUSB_LIBS) $(GLIB_LIBS) $(IMAGEMAGICK_LIBS) libfprint_la_SOURCES = \ fp_internal.h \ diff --git a/libfprint/drivers/aes4000.c b/libfprint/drivers/aes4000.c index 8f732b3..58e1e76 100644 --- a/libfprint/drivers/aes4000.c +++ b/libfprint/drivers/aes4000.c @@ -218,6 +218,7 @@ struct fp_img_driver aes4000_driver = { .flags = 0, .img_height = 96, .img_width = 96, + .enlarge_factor = 3, .init = dev_init, .exit = dev_exit, diff --git a/libfprint/fp_internal.h b/libfprint/fp_internal.h index 361969d..f32fc55 100644 --- a/libfprint/fp_internal.h +++ b/libfprint/fp_internal.h @@ -126,6 +126,7 @@ struct fp_img_driver { uint16_t flags; int img_width; int img_height; + unsigned int enlarge_factor; /* Device operations */ int (*init)(struct fp_img_dev *dev, unsigned long driver_data); diff --git a/libfprint/img.c b/libfprint/img.c index 4e376d2..72504ae 100644 --- a/libfprint/img.c +++ b/libfprint/img.c @@ -23,6 +23,7 @@ #include #include +#include #include "fp_internal.h" #include "nbis/include/bozorth.h" @@ -226,6 +227,50 @@ API_EXPORTED void fp_img_standardize(struct fp_img *img) } } +static struct fp_img *im_resize(struct fp_img *img, unsigned int factor) +{ + Image *mimg; + Image *resized; + ExceptionInfo *exception; + MagickBooleanType ret; + int new_width = img->width * factor; + int new_height = img->height * factor; + struct fp_img *newimg; + + /* It is possible to implement resizing using a simple algorithm, however + * we use ImageMagick because it applies some kind of smoothing to the + * result, which improves matching performances in my experiments. */ + + if (!IsMagickInstantiated()) + MagickCoreGenesis(NULL, MagickFalse); + + exception = AcquireExceptionInfo(); + + mimg = ConstituteImage(img->width, img->height, "I", CharPixel, img->data, exception); + + ClearMagickException(exception); + resized = ResizeImage(mimg, new_width, new_height, 0, 1.0, exception); + + newimg = fpi_img_new(new_width * new_height); + newimg->width = new_width; + newimg->height = new_height; + newimg->flags = img->flags; + + ClearMagickException(exception); + ret = ExportImagePixels(resized, 0, 0, new_width, new_height, "I", + CharPixel, newimg->data, exception); + if (ret != MagickTrue) { + fp_err("export failed"); + return NULL; + } + + DestroyImage(mimg); + DestroyImage(resized); + DestroyExceptionInfo(exception); + + return newimg; +} + /* Based on write_minutiae_XYTQ and bz_load */ static void minutiae_to_xyt(MINUTIAE *minutiae, int bwidth, int bheight, unsigned char *buf) @@ -261,7 +306,7 @@ static void minutiae_to_xyt(MINUTIAE *minutiae, int bwidth, xyt->nrows = nmin; } -int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img, +int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *_img, struct fp_print_data **ret) { MINUTIAE *minutiae; @@ -272,8 +317,20 @@ int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img, unsigned char *bdata; int bw, bh, bd; struct fp_print_data *print; + struct fp_img_driver *imgdrv = fpi_driver_to_img_driver(imgdev->dev->drv); + struct fp_img *img = _img; + int free_img = 0; GTimer *timer; + if (imgdrv->enlarge_factor) { + /* FIXME: enlarge_factor should not exist! instead, MINDTCT should + * actually look at the value of the pixels-per-mm parameter and + * figure out itself when the image needs to be treated as if it + * were bigger. */ + img = im_resize(_img, imgdrv->enlarge_factor); + free_img = 1; + } + /* 25.4 mm per inch */ timer = g_timer_new(); r = get_minutiae(&minutiae, &quality_map, &direction_map, @@ -284,6 +341,8 @@ int fpi_img_detect_minutiae(struct fp_img_dev *imgdev, struct fp_img *img, g_timer_stop(timer); fp_dbg("minutiae scan completed in %f secs", g_timer_elapsed(timer, NULL)); g_timer_destroy(timer); + if (free_img) + g_free(img); if (r) { fp_err("get minutiae failed, code %d", r); return r;