robertvazan / sourceafis-java

Fingerprint recognition engine for Java that takes a pair of human fingerprint images and returns their similarity score. Supports efficient 1:N search.
https://sourceafis.machinezoo.com/java
Apache License 2.0
245 stars 100 forks source link

The threshold of 40 seems risky! #22

Closed Athuli7 closed 4 years ago

Athuli7 commented 4 years ago

Main.java

package com.scalexy.marif;

import com.machinezoo.sourceafis.FingerprintImage;
import com.machinezoo.sourceafis.FingerprintMatcher;
import com.machinezoo.sourceafis.FingerprintTemplate;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.stream.Stream;
import java.lang.instrument.Instrumentation;

public class Main {

    private static Instrumentation instrumentation;

    public static void main(String[] args) throws IOException {
        System.out.println("Started !");
        User users[] =  new User[0];
        long pointInTime = System.nanoTime();
        File folder = new File("src/main/resources/");
        File[] listOfFiles = folder.listFiles();
        for (File file : listOfFiles) {
            if (file.isFile()) {
                pointInTime = System.nanoTime();
                byte[] tempImage = Files.readAllBytes(Paths.get(file.getAbsolutePath()));
                FingerprintTemplate tempTemplate = new FingerprintTemplate(new FingerprintImage().dpi(500).decode(tempImage));
                users = arrayUserPush(new User(file.getName(), tempTemplate), users);

                System.out.println(". Took " + ( ( System.nanoTime() - pointInTime ) / 1000000 ) + " ms");
            }
        }
        for (User user1 : users) {
            FingerprintMatcher user1Probe = new FingerprintMatcher().index(user1.template);
            for (User user2 : users) {
                pointInTime = System.nanoTime();
                double score = user1Probe.match(user2.template);
                if(score > 40) {
                    String user1FingerId = user1.filename.substring(0, 5);
                    String user2FingerId = user2.filename.substring(0, 5);
                    String user1Id = user1.filename.substring(0, 3);
                    String user2Id = user2.filename.substring(0, 3);
                    if(!user1FingerId.equals(user2FingerId)){
                        System.out.println("Mismatched fingers");
                        System.out.println("Took " + ((System.nanoTime() - pointInTime) / 1000000) + " ms to calculate score of " + score + " between " + user1.filename + "[" + user1FingerId + "] and " + user2.filename + "[" + user2FingerId + "]");
                    }
                    if(!user1Id.equals(user2Id)) {
                        System.out.println("Mismatched users");
                        System.out.println("Took " + ((System.nanoTime() - pointInTime) / 1000000) + " ms to calculate score of " + score + " between " + user1.filename + "[" + user1FingerId + "] and " + user2.filename + "[" + user2FingerId + "]");
                    }
//                    System.out.println("Took " + ((System.nanoTime() - pointInTime) / 1000000) + " ms to calculate score of " + score + " between " + user1.filename + "[" + user1FingerId + "] and " + user2.filename + "[" + user2FingerId + "]");
                }
            }
        }

//        FingerprintTemplate f012_3_1 =
//
//        double score = new FingerprintMatcher()
//                .index(probe)
//                .match(candidate);
        System.out.println("Ended with score of " + 0 + "!");
    }
    public static void addToTemplates(Path path) {
        System.out.println(path);
    }

    public static User[] arrayUserPush(User item, User[] oldArray) {
        int len = oldArray.length;
        User[] newArray = new User[len+1];
        System.arraycopy(oldArray, 0, newArray, 0, len);
        newArray[len] = item;
        return newArray;
    }
}

User.java

package com.scalexy.marif;

import com.machinezoo.sourceafis.FingerprintTemplate;

import java.io.File;

public class User {
    public String filename;
    public FingerprintTemplate template;
    public User(String filename, FingerprintTemplate template) {
        this.filename = filename;
        this.template = template;
    }
}

Problem section of console output

Mismatched fingers
Took 0 ms to calculate score of 46.83419575414075 between 045_6_4.tif[045_6] and 013_6_6.tif[013_6]
Mismatched users
Took 0 ms to calculate score of 46.83419575414075 between 045_6_4.tif[045_6] and 013_6_6.tif[013_6]
Mismatched fingers
Took 0 ms to calculate score of 47.15536445186042 between 045_4_7.tif[045_4] and 045_8_2.tif[045_8]
Mismatched fingers
Took 0 ms to calculate score of 48.89576763560057 between 012_5_2.tif[012_5] and 017_4_7.tif[017_4]
Mismatched users
Took 0 ms to calculate score of 48.89576763560057 between 012_5_2.tif[012_5] and 017_4_7.tif[017_4]
Mismatched fingers
Took 0 ms to calculate score of 40.19906861819457 between 013_4_3.tif[013_4] and 017_4_2.tif[017_4]
Mismatched users
Took 0 ms to calculate score of 40.19906861819457 between 013_4_3.tif[013_4] and 017_4_2.tif[017_4]
Mismatched fingers
Took 0 ms to calculate score of 50.304437365351085 between 047_4_6.tif[047_4] and 047_3_5.tif[047_3]
Mismatched fingers
Took 0 ms to calculate score of 46.83419575414075 between 013_6_6.tif[013_6] and 045_6_4.tif[045_6]
Mismatched users
Took 0 ms to calculate score of 46.83419575414075 between 013_6_6.tif[013_6] and 045_6_4.tif[045_6]
Mismatched fingers
Took 0 ms to calculate score of 42.09368749239653 between 012_8_2.tif[012_8] and 017_7_7.tif[017_7]
Mismatched users
Took 0 ms to calculate score of 42.09368749239653 between 012_8_2.tif[012_8] and 017_7_7.tif[017_7]
Mismatched fingers
Took 0 ms to calculate score of 48.89576763560057 between 017_4_7.tif[017_4] and 012_5_2.tif[012_5]
Mismatched users
Took 0 ms to calculate score of 48.89576763560057 between 017_4_7.tif[017_4] and 012_5_2.tif[012_5]

The threshold of 40 is triggering false positives. This is nowhere close to 0.01 FAR. Or am I doing something wrong?

Athuli7 commented 4 years ago

I'm using the linked fingerprint database.

robertvazan commented 4 years ago

Which dataset is this? Judging by filenames, this is one of the Neurotech datasets that contain 400-500 fingerprints that form 160K-250K pairs, most of them non-matching. Finding 14 false matches in so many pairs is actually very close to 0.01% FMR.

Nevertheless, the relationship between threshold and FMR is approximate. If your dataset contains large prints with lots of minutiae, you should probably raise the threshold a bit.