Цифровая персона SDK - родные проблемы - PullRequest
0 голосов
/ 26 апреля 2020

Я использую в приложении Digital Persona SDK для идентификации отпечатков пальцев. Когда я использую функцию идентификации на менее чем 250 fmds, она работает нормально.

Engine.Candidate candidates[] = m_engine.Identify(searchedFmd, 0, fmdArray, DEFAULT_THRESHOLD, 1); //fmdArray < 250

Но с fmdArray> 250 это дает мне собственную ошибку времени выполнения:

A/art: art/runtime/indirect_reference_table.cc:132] JNI ERROR (app bug): local reference table overflow (max=512)

Теперь я запустил это приложение на пару android устройств и пришел к выводу, что мое приложение ломается с fmdArray> 250, когда оно работает на android 7. Но android 8 работает нормально. В 8 я могу выполнить проверку на 4000 фмдс, и она отлично работает.

Но мне нужно запустить этот код на определенном c устройстве, которое работает android 7.

Я пытался запустить его только в нескольких потоках 250 fmds. Но после одиночного запуска есть еще одна проблема с SDK. При втором запуске это не работает.

Это то, что я делаю: Сначала я получаю захват отпечатка пальца, который я хочу идентифицировать:

Reader.CaptureResult capture = m_reader.Capture(fidFormat, UrUSDK.DefaultImageProcessing, m_DPI, timeout);
// In second run, code after this line is not executed.
// My guees its not coming back from native. No exeptions. No errors.
...
Fmd scannedFmd = m_engine.CreateFmd(capture.image, fmdFormat);
...
int index = identifyFinger(fmds, scannedFmd);
...

    private int identifyFinger(List<Fmd> fmdSearchArray, Fmd scannedFmd) {
        List<List<Fmd>> lists = splitToChunks(fmdSearchArray);
        AtomicInteger index = new AtomicInteger(-1);
        List<Callable<Void>> threads = new ArrayList<>(lists.size());
        AtomicInteger iteratorIndex = new AtomicInteger(0);
        for (int i = 0; i < lists.size(); i++) {
            int currentChunk = i;
            Callable<Void> thread = () -> {
                System.out.println(Thread.currentThread().getName() + " with chunk: " + iteratorIndex.getAndIncrement());
                Fmd[] fmds = lists.get(currentChunk).toArray(new Fmd[IDENTIFY_BOUNDARY]);
                try {
                    Engine.Candidate[] candidates = m_engine.Identify(scannedFmd, 0, fmds, threshold, 1);
                    if (candidates.length > 0) {
                        index.set(candidates[0].fmd_index + (currentChunk * IDENTIFY_BOUNDARY));
                    }
                } catch (UareUException e) {

                }
                System.out.println(Thread.currentThread().getName() + " with chunk: " + currentChunk + " finished!");
                return null;
            };
            threads.add(thread);
        }

        try {
            List<Future<Void>> futures = executorService.invokeAll(threads);
            System.out.println("All threads finished: " + index.get());
            return index.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
            return -1;
        }
    }

...

private List<List<Fmd>> splitToChunks(List<Fmd> fmdSearchArray) {
        int size = fmdSearchArray.size();
        List<List<Fmd>> lists;
        if (size > IDENTIFY_BOUNDARY) {
            int chunks = size / IDENTIFY_BOUNDARY;
            if (size % IDENTIFY_BOUNDARY > 0) {
                chunks++;
            }
            lists = new ArrayList<>(chunks);
            for (int i = 0; i < chunks; i++) {
                if (i + 1 == chunks) {
                    lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, size)));
                    break;
                }
                lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, (i + 1) * IDENTIFY_BOUNDARY)));
            }
        } else {
            lists = new ArrayList<>(1);
            lists.add(fmdSearchArray);
        }
        return lists;
    }

Проблема с этим кодом заключается в том, что он работает один раз. Но с другой попытки он не возвращается из нативного кода вызова Caprture.

Итак, мой вопрос: как я могу преодолеть это и заставить его работать из моего java кода? Или хотя бы каково направление решения?

1 Ответ

0 голосов
/ 27 апреля 2020

Причина root заключается в том, что эта функция Identify удерживает как минимум две ссылки на возвращаемую Candidate после отправки ее в массив результатов. Вместо этого он должен освобождать ссылки после нажатия, поэтому его использование (ограниченной) локальной таблицы ссылок остается постоянным. Вы должны сообщить об этом.

Самый простой обходной путь на данный момент - разрезать ваши fmdArray на куски размером 250 и вызывать Identify для каждого кусочка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...