All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.machinezoo.sourceafis.FingerprintTemplate Maven / Gradle / Ivy

Go to download

Fingerprint recognition engine that takes a pair of human fingerprint images and returns their similarity score. Supports efficient 1:N search.

There is a newer version: 3.18.1
Show newest version
// Part of SourceAFIS for Java: https://sourceafis.machinezoo.com/java
package com.machinezoo.sourceafis;

import java.util.*;
import javax.imageio.*;
import org.slf4j.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonAutoDetect.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.dataformat.cbor.*;
import com.google.gson.*;
import com.machinezoo.fingerprintio.*;
import com.machinezoo.noexception.*;

/**
 * Biometric description of a fingerprint suitable for efficient matching.
 * Fingerprint template holds high-level fingerprint features, specifically ridge endings and bifurcations (together called minutiae).
 * Original image is not preserved in the fingerprint template and there is no way to reconstruct the original fingerprint from its template.
 * 

* {@link FingerprintImage} can be converted to template by calling {@link #FingerprintTemplate(FingerprintImage)} constructor. *

* Since image processing is expensive, applications should cache serialized templates. * Serialization into CBOR format is performed by {@link #toByteArray()} method. * CBOR template can be deserialized by calling {@link #FingerprintTemplate(byte[])} constructor. *

* Matching is performed by constructing {@link FingerprintMatcher}, * passing probe fingerprint to its {@link FingerprintMatcher#FingerprintMatcher(FingerprintTemplate)} constructor, * and then passing candidate fingerprints to its {@link FingerprintMatcher#match(FingerprintTemplate)} method. *

* {@code FingerprintTemplate} contains two kinds of data: fingerprint features and search data structures. * Search data structures speed up matching at the cost of some RAM. * Only fingerprint features are serialized. Search data structures are recomputed after every deserialization. * * @see SourceAFIS for Java tutorial * @see FingerprintImage * @see FingerprintMatcher */ public class FingerprintTemplate { /* * API roadmap: * + FingerprintTemplate(FingerprintImage, FingerprintTemplateOptions) * + double surface() - in metric units * + FingerprintPosition position() * + other fingerprint properties set in FingerprintImageOptions (only those relevant to matching, so no width/height for example) * + FingerprintModel model() * + FingerprintTemplate(FingerprintModel) * + FingerprintTemplate narrow(FingerprintTemplateOptions) - for reducing RAM usage by dropping features * + byte[] pack(int limit) - for producing super-compact templates (even under 100 bytes) * + FingerprintTemplate unpack(byte[] packed) * * FingerprintTemplateOptions: * + featureX(boolean) - enable/disable production of expensive fingerprint features * + parallelize(boolean) * + cpu(long) - limit on CPU cycles consumed (approximate) * * FingerprintModel: * = editing-optimized fingerprint representation as opposed to matching- and serialization-optimized FingerprintTemplate * = to be used in forensics and other settings for fingerprint editing * - no DPI, all values in metric units * + double width/height() * + List minutiae() - mutable list of mutable minutiae * + all properties exposed by FingerprintTemplate * + setters for everything * * FingerprintMinutia: * + double x/y() * + double direction() * + also setters * * FingerprintFusion: * + add(FingerprintTemplate) * + FingerprintTemplate fuse() */ static { PlatformCheck.run(); } /* * We should drop this indirection once deprecated methods are dropped * and FingerprintTemplate itself becomes immutable. */ volatile ImmutableTemplate immutable = ImmutableTemplate.EMPTY; private static final Logger logger = LoggerFactory.getLogger(FingerprintTemplate.class); /** * Creates fingerprint template from fingerprint image. *

* This constructor runs an expensive feature extractor algorithm, * which analyzes the image and collects identifiable biometric features from it. * * @param image * fingerprint image to process * @throws NullPointerException * if {@code image} is {@code null} */ public FingerprintTemplate(FingerprintImage image) { Objects.requireNonNull(image); immutable = new ImmutableTemplate(FeatureExtractor.extract(image.matrix, image.dpi)); } /** * Deserializes fingerprint template from byte array. * This constructor reads CBOR-encoded template produced by {@link #toByteArray()} * and reconstructs an exact copy of the original fingerprint template. *

* Templates produced by previous versions of SourceAFIS may fail to deserialize correctly. * Applications should re-extract all templates from original images when upgrading SourceAFIS. * * @param serialized * serialized fingerprint template in CBOR format produced by {@link #toByteArray()} * @throws NullPointerException * if {@code serialized} is {@code null} * @throws RuntimeException * if {@code serialized} is not in the correct format or it is corrupted * * @see #toByteArray() * @see Template format * @see FingerprintImage#FingerprintImage(byte[]) * @see FingerprintCompatibility#importTemplate(byte[]) */ public FingerprintTemplate(byte[] serialized) { this(serialized, true); } private static final ObjectMapper mapper = new ObjectMapper(new CBORFactory()) .setVisibility(PropertyAccessor.FIELD, Visibility.ANY); FingerprintTemplate(byte[] serialized, boolean foreignToo) { try { Objects.requireNonNull(serialized); PersistentTemplate persistent = mapper.readValue(serialized, PersistentTemplate.class); persistent.validate(); immutable = new ImmutableTemplate(persistent.mutable()); } catch (Throwable ex) { if (!foreignToo) throw new IllegalArgumentException("This is not a valid SourceAFIS template.", ex); try { FingerprintTemplate converted = FingerprintCompatibility.importTemplate(serialized); immutable = converted.immutable; /* * It is an error to pass foreign template here, so at least log a warning. */ logger.warn("Template in non-native format was passed to FingerprintTemplate constructor. " + "It was accepted, but FingerprintCompatibility.importTemplate() should be used instead."); } catch (Throwable ex2) { /* * Throw the original exception. We don't want to hide it with exception from this fallback. */ throw new IllegalArgumentException("This is not a valid SourceAFIS template.", ex); } } } /** * @deprecated Use one of the constructors that take parameters to create fully initialized template instead. * * @see #FingerprintTemplate(FingerprintImage) * @see #FingerprintTemplate(byte[]) */ @Deprecated public FingerprintTemplate() { } /** * Gets the empty fallback template with no biometric data. * Empty template is useful as a fallback to simplify code. * It contains no biometric data and it does not match any other template including itself. * There is only one global instance. This method does not instantiate any new objects. * * @return empty template */ public static FingerprintTemplate empty() { return EMPTY; } private static final FingerprintTemplate EMPTY = new FingerprintTemplate(ImmutableTemplate.EMPTY); FingerprintTemplate(ImmutableTemplate immutable) { this.immutable = immutable; } /** * @deprecated Use thread-local instance of {@link FingerprintTransparency} instead. * * @param transparency * target {@link FingerprintTransparency} or {@code null} to disable algorithm transparency * @return {@code this} (fluent method) * * @see FingerprintTransparency */ @Deprecated public FingerprintTemplate transparency(FingerprintTransparency transparency) { return this; } private double dpi = 500; /** * @deprecated Set DPI via {@link FingerprintImageOptions}{@link #dpi(double)} instead. * * @param dpi * DPI of the fingerprint image, usually around 500 * @return {@code this} (fluent method) * * @see FingerprintImageOptions#dpi(double) */ @Deprecated public FingerprintTemplate dpi(double dpi) { this.dpi = dpi; return this; } /** * @deprecated Use {@link #FingerprintTemplate(FingerprintImage)} constructor to create template from image. * * @param image * fingerprint image in {@link ImageIO}-supported format * @return {@code this} (fluent method) * * @see #FingerprintTemplate(FingerprintImage) */ @Deprecated public FingerprintTemplate create(byte[] image) { immutable = new ImmutableTemplate(FeatureExtractor.extract(new FingerprintImage(image).matrix, dpi)); return this; } /** * @deprecated Use {@link #FingerprintTemplate(byte[])} constructor to deserialize the template. * * @param json * serialized fingerprint template in JSON format produced by {@link #serialize()} * @return {@code this} (fluent method) * @throws NullPointerException * if {@code json} is {@code null} * @throws RuntimeException * if {@code json} is is not in the correct format or it is corrupted * * @see #FingerprintTemplate(byte[]) */ @Deprecated public FingerprintTemplate deserialize(String json) { Objects.requireNonNull(json); PersistentTemplate persistent = new Gson().fromJson(json, PersistentTemplate.class); persistent.validate(); immutable = new ImmutableTemplate(persistent.mutable()); return this; } /** * Serializes fingerprint template into byte array. * Serialized template can be stored in a database or sent over network. * It can be then deserialized by calling {@link #FingerprintTemplate(byte[])} constructor. * Persisting templates alongside fingerprint images allows applications to start faster, * because template deserialization is more than 100x faster than re-extraction from fingerprint image. *

* Serialized template excludes search structures that {@code FingerprintTemplate} keeps to speed up matching. * Serialized template is therefore much smaller than in-memory {@code FingerprintTemplate}. *

* Serialization format can change with every SourceAFIS version. There is no backward compatibility of templates. * Applications should preserve raw fingerprint images, so that templates can be re-extracted after SourceAFIS upgrade. * Template format for current version of SourceAFIS is * documented on SourceAFIS website. * * @return serialized fingerprint template in CBOR format * * @see #FingerprintTemplate(byte[]) * @see Template format * @see FingerprintCompatibility#exportTemplates(TemplateFormat, FingerprintTemplate...) */ public byte[] toByteArray() { PersistentTemplate persistent = new PersistentTemplate(immutable.mutable()); return Exceptions.wrap().get(() -> mapper.writeValueAsBytes(persistent)); } /** * @deprecated Use {@link #toByteArray()} to serialize the template. * * @return serialized fingerprint template in JSON format * * @see #toByteArray() */ @Deprecated public String serialize() { return new Gson().toJson(new PersistentTemplate(immutable.mutable())); } /** * @deprecated Use {@link FingerprintCompatibility} methods to import other template formats. * * @param template * foreign template to import * @return {@code this} (fluent method) * * @see FingerprintCompatibility#convert(byte[]) */ @Deprecated public FingerprintTemplate convert(byte[] template) { immutable = FingerprintCompatibility.convert(template).immutable; return this; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy