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

Call Java functions from Python #63

Closed kevinzezel closed 9 months ago

kevinzezel commented 9 months ago

Hi,

Would you have an example of how I can call java functions with a wrapper in python?

Regards, Kevin

robertvazan commented 9 months ago

There's no easy way to do that. You would have to wrap the library in a REST service and then access it from Python. Or perhaps there are better ways, but this is general Java/Python question that is not specific to SourceAFIS. Although I would like to implement Python port eventually, I do not have time for it now and it's not a sourceafis-java issue anyway as the port should be ideally standalone or based on native library (Rust), so I am closing this issue here.

kpoman commented 9 months ago

I had some success using jpype, or the dotnet version, from python.

kpoman commented 9 months ago

See below an example of an old code I have:


import datetime
import gzip
import json
import os
import sys
import time
import zipfile

import expybio
from expybio.common.fingerimage import FingerImage
from expybio.matcher.base import BiometricsMatcher
import xml.etree.ElementTree as ET
import io
import math

import jpype
import jpype.imports

current_directory = os.path.dirname(os.path.abspath(__file__))
jar_file = os.path.join(current_directory, 'sourceafis-3.8.1-jar-with-dependencies.jar')
jpype.addClassPath(jar_file)
jar_file = os.path.join(current_directory, 'sourceafis-visualization-0.4.1-jar-with-dependencies.jar')
jpype.addClassPath(jar_file)
jpype.startJVM(convertStrings=True)
from com.machinezoo.sourceafis import FingerprintImage, FingerprintTemplate, FingerprintMatcher, FingerprintTransparency
import java.io

class SAMatcher(BiometricsMatcher):

    def __init__(self):
        super().__init__()
        self.matcher_type = 'fingerprint'
        self.matcher_modes = ['1:1', '1:N']
        self.max_records = 1000
        self.vendor = 'robertvazan@github'
        self.product = 'SourceAFISv3.8.1'
        self.generate_uuid()

    def _vnd_minutiae(self, rec):
        return self.__get_vendor_minutiae(rec)

    def __get_vendor_minutiae(self, rec):
        # we must convert our minutia object to SourceAFIS format which is xml
        expybio.logger.info('__get_vendor_minutiae')
        obj = {'version':'3.8.1', 'minutiae':[]}
        try:
            obj['width'] = rec['width']
            obj['height'] = rec['height']
        except Exception as e:
            pass
        minutiae = rec['minutiae']
        for m in minutiae:
            minutia = {}
            minutia['x'] = m['x']
            minutia['y'] = m['y']
            a = (m['a'] + 180)%360
            if a == 0:
                a = 360
            minutia['direction'] = 2*math.pi - (a/360.)*2*math.pi
            minutia['type'] = 'bifurcation' if m['t']==0 else 'ending'
            obj['minutiae'].append(minutia)
        json_obj = json.dumps(obj)
        s = gzip.compress(json_obj.encode('utf-8'))
        text_trap = io.StringIO()
        sys.stdout = text_trap
        template = FingerprintTemplate(s)
        sys.stdout = sys.__stdout__
        return template

    def _vnd_add_rec_to_gal(self, rec, gal):
        expybio.logger.info('_vnd_add_rec_to_gal')
        print('enroll', rec['id'])
        template = self.__get_vendor_minutiae(rec)
        self.galleries[gal][rec['id']] = {'template':template}

    def _vnd_identify(self, rec, gal, metadata=False):
        expybio.logger.info('_vnd_identify')
        reference_template = self.__get_vendor_minutiae(rec)
        probe = FingerprintMatcher().index(reference_template)
        results = {}
        for r in self.galleries[gal]:
            if metadata:
                out = io.BytesIO()
                zipped = java.io.ByteArrayOutputStream()
                transparency = FingerprintTransparency.zip(zipped)
            score = probe.match(self.galleries[gal][r]['template'])
            results[r] = {'score':score, 'metadata':None}
            if metadata:
                transparency.close()
                out.write(zipped.toByteArray()[:])
                out.seek(0)
                extradata = {}
                zip = zipfile.ZipFile(out)
                for info in zip.namelist():
                    extradata[info] = zip.read(info)
                results[r]['metadata'] = extradata
        if metadata:
            retval = sorted(results.items(), key=lambda kv: kv[1]['score'], reverse=True)
        else:
            retval = sorted(results.items(), key=lambda kv: kv[1], reverse=True)
        return retval

    def load_probe(self):
        probe = open('/mnt/windows/tmp/sourceafis-java-master/src/test/resources/com/machinezoo/sourceafis/probe.png', 'rb').read()
        #{"version":"3.8.1","width":388,"height":374,"minutiae":
        # [{"x":74,"y":136,"direction":1.9513027039072617,"type":"ending"}, {"x":80,"y":156,"direction":1.9936502529278375,"type":"ending"}, ...
        fp = FingerprintImage().decode(probe)
        text_trap = io.StringIO()
        sys.stdout = text_trap
        template = FingerprintTemplate(fp)
        sys.stdout = sys.__stdout__
        FingerprintMatcher().index(template).match(template)

if __name__ == '__main__':
    m = SAMatcher()
    m.load_probe()

Hope this helps! Let me know if you need anything else.

kevinzezel commented 9 months ago

Nice, thank you!

How can i generate jar with dependencies?