Я реализовал на Java метод проверки учащихся по отпечаткам пальцев. Этот метод основан на библиотеке SourceAFIS для сопоставления отпечатков пальцев и предназначен для одновременной обработки нескольких отпечатков пальцев. Однако когда количество студентов около 50, время ответа составляет примерно 10 секунд, что слишком медленно для нашего варианта использования.
Подход
Асинхронная загрузка расписания и учащихся.
Используйте CompletableFuture для одновременной загрузки расписания и связанных с ним учащихся.
Пакетная обработка отпечатков пальцев:
Извлечение отпечатков пальцев всех учащихся.
Разделение отпечатков пальцев на меньшие пакеты в зависимости от количества доступных процессоров.
Обрабатывать пакеты параллельно с помощью CompletableFuture и пользовательского пула потоков.
< /li>
Логика сопоставления с использованием SourceAFIS:
Используйте классы FingerprintTemplate и FingerprintMatcher из библиотеки SourceAFIS, чтобы сравнить отпечаток зонда с каждым отпечатком пальца в пакете.
Определите лучшее совпадение с показателем сходства выше определенного порога.
@Override
public User verifyStudentFingerprint(Long scheduleId, MultipartFile scannedFingerprintImage) throws IOException {
// Cache the scanned template first to avoid redundant conversions
byte[] scannedFingerprintImageBytes = scannedFingerprintImage.getBytes();
FingerprintTemplate probeTemplate = new FingerprintTemplate(
new FingerprintImage(scannedFingerprintImageBytes)
);
// Fetch schedule and students in parallel using CompletableFuture
CompletableFuture scheduleFuture = CompletableFuture.supplyAsync(() ->
scheduleRepository.findById(scheduleId).orElse(null)
);
CompletableFuture[*]> studentsFuture = scheduleFuture.thenApplyAsync(schedule ->
schedule != null ? scheduleStudentRepository.findByScheduleId(schedule.getId()) : Collections.emptyList()
);
// Wait for both futures to complete
Schedule schedule = scheduleFuture.join();
List students = studentsFuture.join();
if (schedule == null || students.isEmpty()) return null;
// Extract student IDs and fetch fingerprints
List studentIds = students.stream()
.map(s -> s.getStudent().getId())
.collect(Collectors.toList());
// Use batch fetching for fingerprints
List fingerprints = fingerprintRepository.getOneFingerprintPerUser(studentIds);
if (fingerprints.isEmpty()) return null;
// Create a thread pool with the number of available processors
int processors = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = Executors.newFixedThreadPool(processors);
try {
// Process fingerprints in batches
int batchSize = Math.max(1, fingerprints.size() / processors);
List batches = partitionList(fingerprints, batchSize);
// Create tasks for parallel processing
List futures = batches.stream()
.map(batch -> CompletableFuture.supplyAsync(() -> processFingerprintBatch(batch, probeTemplate), executorService))
.toList();
// Find the best match across all batches
Optional bestMatch = futures.stream()
.map(CompletableFuture::join)
.filter(Optional::isPresent)
.map(Optional::get)
.max(Map.Entry.comparingByValue());
if (bestMatch.isEmpty() || bestMatch.get().getValue() < threshold) {
return null;
}
// Update attendance status
Fingerprint matchedFingerprint = bestMatch.get().getKey();
ScheduleStudent matchedStudent = students.stream()
.filter(s -> s.getStudent().getId().equals(matchedFingerprint.getUser().getId()))
.findFirst()
.orElse(null);
if (matchedStudent != null) {
matchedStudent.setHasLogged(true);
scheduleStudentRepository.save(matchedStudent);
return matchedFingerprint.getUser();
}
return null;
} finally {
executorService.shutdown();
}
}
private List partitionList(List list, int batchSize) {
if (batchSize list.subList(
i * batchSize,
Math.min((i + 1) * batchSize, list.size())
))
.collect(Collectors.toList());
}
private Optional processFingerprintBatch(
List batch,
FingerprintTemplate probeTemplate
) {
FingerprintMatcher matcher = new FingerprintMatcher(probeTemplate);
return batch.parallelStream()
.map(fingerprint -> {
FingerprintTemplate template = new FingerprintTemplate(
new FingerprintImage(fingerprint.getFingerprint())
);
return Map.entry(fingerprint, matcher.match(template));
})
.filter(entry -> entry.getValue() >= threshold)
.max(Map.Entry.comparingByValue());
}
Проблема
Метод работает правильно, но слишком медленно. Для 50 студентов обработка занимает около 10 секунд, что влияет на удобство использования. Я считаю, что узким местом может быть:
Преобразование изображений отпечатков пальцев в объекты FingerprintTemplate.
Процесс сопоставления с использованием FingerprintMatcher. .
Что я пробовал
Разделение отпечатков пальцев на пакеты и обработка их параллельно, используя пул потоков.
Использование ParallelStream для обработки отпечатков пальцев в каждом пакете.
Регулировка размера пакета для снижения накладных расходов.
< h4>Вопросы
Существуют ли какие-либо передовые методы оптимизации сопоставления отпечатков пальцев с помощью SourceAFIS, особенно для пакетной обработки?
Можно ли? процесс преобразования изображения в шаблон становится узким местом? Если да, то как я могу его оптимизировать?
Существуют ли альтернативные подходы или архитектурные изменения, которые могли бы сократить время обработки?
Изменить: дополнительный контекст
Я использую SourceAFIS 3.18.1 для Java.
Изображения отпечатков пальцев хранятся в базе данных в виде двоичных данных и извлекаются в виде байтов. массивы.
Я реализовал на Java метод проверки учащихся по отпечаткам пальцев. Этот метод основан на библиотеке SourceAFIS для сопоставления отпечатков пальцев и предназначен для одновременной обработки нескольких отпечатков пальцев. Однако когда количество студентов около 50, время ответа составляет примерно 10 секунд, что слишком медленно для нашего варианта использования. [h4]Подход[/h4] [list] [*]Асинхронная загрузка расписания и учащихся. [list] Используйте CompletableFuture для одновременной загрузки расписания и связанных с ним учащихся. [/list]
[*]Пакетная обработка отпечатков пальцев: [list] Извлечение отпечатков пальцев всех учащихся. [*]Разделение отпечатков пальцев на меньшие пакеты в зависимости от количества доступных процессоров. [*]Обрабатывать пакеты параллельно с помощью CompletableFuture и пользовательского пула потоков. [/list] < /li> [*]Логика сопоставления с использованием SourceAFIS: [list] Используйте классы FingerprintTemplate и FingerprintMatcher из библиотеки SourceAFIS, чтобы сравнить отпечаток зонда с каждым отпечатком пальца в пакете. [*]Определите лучшее совпадение с показателем сходства выше определенного порога. [/list]
[/list] Уровень обслуживания: [code] @Override public User verifyStudentFingerprint(Long scheduleId, MultipartFile scannedFingerprintImage) throws IOException { // Cache the scanned template first to avoid redundant conversions byte[] scannedFingerprintImageBytes = scannedFingerprintImage.getBytes(); FingerprintTemplate probeTemplate = new FingerprintTemplate( new FingerprintImage(scannedFingerprintImageBytes) );
// Fetch schedule and students in parallel using CompletableFuture CompletableFuture scheduleFuture = CompletableFuture.supplyAsync(() -> scheduleRepository.findById(scheduleId).orElse(null) );
// Wait for both futures to complete Schedule schedule = scheduleFuture.join(); List students = studentsFuture.join();
if (schedule == null || students.isEmpty()) return null;
// Extract student IDs and fetch fingerprints List studentIds = students.stream() .map(s -> s.getStudent().getId()) .collect(Collectors.toList());
// Use batch fetching for fingerprints List fingerprints = fingerprintRepository.getOneFingerprintPerUser(studentIds); if (fingerprints.isEmpty()) return null;
// Create a thread pool with the number of available processors int processors = Runtime.getRuntime().availableProcessors(); ExecutorService executorService = Executors.newFixedThreadPool(processors);
try { // Process fingerprints in batches int batchSize = Math.max(1, fingerprints.size() / processors); List batches = partitionList(fingerprints, batchSize);
// Create tasks for parallel processing List futures = batches.stream() .map(batch -> CompletableFuture.supplyAsync(() -> processFingerprintBatch(batch, probeTemplate), executorService)) .toList();
// Find the best match across all batches Optional bestMatch = futures.stream() .map(CompletableFuture::join) .filter(Optional::isPresent) .map(Optional::get) .max(Map.Entry.comparingByValue());
if (bestMatch.isEmpty() || bestMatch.get().getValue() < threshold) { return null; }
private List partitionList(List list, int batchSize) { if (batchSize list.subList( i * batchSize, Math.min((i + 1) * batchSize, list.size()) )) .collect(Collectors.toList()); }
private Optional processFingerprintBatch( List batch, FingerprintTemplate probeTemplate ) { FingerprintMatcher matcher = new FingerprintMatcher(probeTemplate);
return batch.parallelStream() .map(fingerprint -> { FingerprintTemplate template = new FingerprintTemplate( new FingerprintImage(fingerprint.getFingerprint()) ); return Map.entry(fingerprint, matcher.match(template)); }) .filter(entry -> entry.getValue() >= threshold) .max(Map.Entry.comparingByValue()); } [/code] [h4]Проблема[/h4] Метод работает правильно, но слишком медленно. Для 50 студентов обработка занимает около 10 секунд, что влияет на удобство использования. Я считаю, что узким местом может быть: [list] Преобразование изображений отпечатков пальцев в объекты FingerprintTemplate. [*]Процесс сопоставления с использованием FingerprintMatcher. . [/list] [h4]Что я пробовал[/h4] [list] [*]Разделение отпечатков пальцев на пакеты и обработка их параллельно, используя пул потоков. [*]Использование ParallelStream для обработки отпечатков пальцев в каждом пакете. [*]Регулировка размера пакета для снижения накладных расходов. [/list] < h4>Вопросы [list] [*]Существуют ли какие-либо передовые методы оптимизации сопоставления отпечатков пальцев с помощью SourceAFIS, особенно для пакетной обработки? [*]Можно ли? процесс преобразования изображения в шаблон становится узким местом? Если да, то как я могу его оптимизировать? [*]Существуют ли альтернативные подходы или архитектурные изменения, которые могли бы сократить время обработки? [/list] [h4]Изменить: дополнительный контекст[/h4] [list] [*]Я использую SourceAFIS 3.18.1 для Java. [*]Изображения отпечатков пальцев хранятся в базе данных в виде двоичных данных и извлекаются в виде байтов. массивы. [/list]
Я хочу сделать веб -сайт, на котором я хочу проверить пользователя по отпечаткам пальцев. Я хочу сохранить пользовательский отпечаток пальцев в базе данных, просто используя сканер отпечатков пальцев Mobile, я не хочу использовать какой -либо...
Я работаю над веб-приложением React-Native и хочу создать новый стиль аутентификации.
вот что я надеюсь сделать: -
Я хочу отсканировать отпечаток пальца пользователя и сохранить его в своей базе данных, а затем вместо того, чтобы сообщать мне имя...
Я проводил небольшое исследование, но так и не нашел ничего, кроме зашифрованной информации и отсутствия необходимых ресурсов...
Я хотел регистрировать пациентов с помощью веб-приложения php. /js... кто-нибудь это сделал? возможно ли это?
Мне просто...
Я пытаюсь проверить свой датчик отпечатков пальцев, он тоже отображается на терминале, но когда я запускаю этот код, появляется эта ошибка:
Traceback (most recent call last): File , line 8, in NameError: name 'adafruit_fingerprint' is not defined...