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.
This commit is contained in:
parent
a73cbc10fb
commit
e3451158e9
5 changed files with 68 additions and 3 deletions
|
@ -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)])],
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <magick/ImageMagick.h>
|
||||
|
||||
#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;
|
||||
|
|
Loading…
Reference in a new issue