2013-03-19 3 views
2

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

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 создателя должен быть, может быть, нет, почему он ничего не узнает ...

ответ

4

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

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

Explaination:

  • Первым параметром является число главных компонент в алгоритме 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)); 
+1

Спасибо за объяснение, это лучше, чем что-либо еще, что я мог найти ... – jjv360