Как оптимизировать сопоставление отпечатков пальцев SourceAFIS для больших списков учащихся?JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Как оптимизировать сопоставление отпечатков пальцев SourceAFIS для больших списков учащихся?

Сообщение Anonymous »

Я реализовал на 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.
  • Изображения отпечатков пальцев хранятся в базе данных в виде двоичных данных и извлекаются в виде байтов. массивы.


Подробнее здесь: https://stackoverflow.com/questions/793 ... dent-lists
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»