Как идентифицировать новые лица с помощью OpenIMAJ

У меня есть живой поток изображений JPG, поступающих в другой поток в моем приложении Java, и я хочу постоянно сканировать лица, чтобы позже вывести список всех разных лиц, которые прошли мимо камеры во время ее работы, и сколько раз видели каждое лицо. Вот мой текущий код:

void doImageProcessing() {

    // Create face stuff
    FKEFaceDetector faceDetector = new FKEFaceDetector(new HaarCascadeDetector());
    EigenFaceRecogniser<KEDetectedFace, Person> faceRecognizer = EigenFaceRecogniser.create(512, new RotateScaleAligner(), 512, DoubleFVComparison.CORRELATION, Float.MAX_VALUE);
    FaceRecognitionEngine<KEDetectedFace, Extractor<KEDetectedFace>, Person> faceEngine = FaceRecognitionEngine.create(faceDetector, faceRecognizer);

    // Start loop
    while (true) {

        // Get next frame
        byte[] imgData = nextProcessingData;
        nextProcessingData = null;

        // Decode image
        BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgData));

        // Detect faces
        FImage fimg = ImageUtilities.createFImage(img);
        List<KEDetectedFace> faces = faceEngine.getDetector().detectFaces(fimg);

        // Go through detected faces
        for (KEDetectedFace face : faces) {

            // Find existing person for this face
            Person person = null;
            try {

                List<IndependentPair<KEDetectedFace, ScoredAnnotation<Person>>> rfaces = faceEngine.recogniseBest(face.getFacePatch());
                ScoredAnnotation<Person> score = rfaces.get(0).getSecondObject();
                if (score != null)
                    person = score.annotation;

            } catch (Exception e) {
            }

            // If not found, create
            if (person == null) {

                // Create person
                person = new Person();
                System.out.println("Identified new person: " + person.getIdentifier());

                // Train engine to recognize this new person
                faceEngine.train(person, face.getFacePatch());

            } else {

                // This person has been detected before
                System.out.println("Identified existing person: " + person.getIdentifier());

            }

        }

    }

}

Проблема в том, что он всегда определяет лицо как новое, даже если это то же самое лицо, которое было обнаружено в предыдущем кадре. rfaces всегда пусто. Он никогда не сможет идентифицировать существующее лицо. Что я делаю не так?

Кроме того, я понятия не имею, какие параметры для EigenFaceRecognizer функция Creator должна быть, может поэтому ничего не распознает...


person jjv360    schedule 19.03.2013    source источник


Ответы (1)


Параметры, которые вы указали для функции EigenFaceRecogniser.create(), неверны, так что, вероятно, это и есть причина ваших проблем. Скорее всего, сработает следующее:

EigenFaceRecogniser<KEDetectedFace, Person> faceRecognizer = EigenFaceRecogniser.create(20, new RotateScaleAligner(), 1, DoubleFVComparison.CORRELATION, 0.9f);

Пояснение:

  • Первый параметр — это количество основных компонентов в алгоритме EigenFace; точное значение обычно определяется экспериментально, но что-то около ~ 20, вероятно, подойдет.

  • Третий параметр — это количество ближайших соседей, которые следует использовать для классификатора KNN. 1 ближайший сосед должен быть в порядке.

  • Последним параметром является пороговое значение расстояния для классификатора. Сравнение корреляции возвращает меру подобия (большие значения означают большее сходство), поэтому заданный порог является нижним пределом, который необходимо превысить. Поскольку мы установили 1 ближайшего соседа, расстояние между наиболее похожим лицом и лицом запроса должно быть больше 0,9. Обратите внимание, что значение 0,9 — это всего лишь предположение. чтобы оптимизировать производительность вашего распознавателя, вам придется поиграть с этим.

Еще один незначительный момент - вместо:

    BufferedImage img = ImageIO.read(new ByteArrayInputStream(imgData));
    FImage fimg = ImageUtilities.createFImage(img);

Как правило, лучше позволить OpenIMAJ прочитать ваше изображение, поскольку он решает ряд известных проблем с обработкой ImageIO определенных типов JPEG:

    FImage fimg = ImageUtilities.readF(new ByteArrayInputStream(imgData));
person Jon    schedule 19.03.2013