2

Java アプリの別のスレッドで JPG 画像のライブ ストリームを受け取りました。顔を継続的にスキャンして、カメラの実行中にカメラを通過したすべての異なる顔のリストと、その数を後で出力したいと考えています。それぞれの顔が見られた回数。これが私の現在のコードです:

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

1 に答える 1

4

関数に指定したパラメーターがかなりEigenFaceRecogniser.create()ずれているため、おそらくそれが問題の原因です。以下は動作する可能性が高くなります。

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

説明:

  • 最初のパラメーターは、EigenFace アルゴリズムの主成分の数です。通常、正確な値は実験的に決定されますが、約 20 程度で十分です。

  • 3 番目のパラメーターは、KNN 分類器に使用する最近傍の数です。1 つの最近傍は問題ないはずです。

  • 最後のパラメーターは、分類子の距離のしきい値です。相関比較は類似度を返します (高い値はより類似していることを意味します)。1 つの最近傍を設定したため、最も類似した顔とクエリの顔の間の距離は 0.9 より大きくなければなりません。0.9 という値は単なる推測であることに注意してください。認識機能のパフォーマンスを最適化するには、これをいじる必要があります。

もう1つのマイナーポイント-代わりに:

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

通常、OpenIMAJ に画像を読み込ませることをお勧めします。OpenIMAJ は、特定の種類の JPEG の ImageIO の処理に関する既知の問題を回避するためです。

    FImage fimg = ImageUtilities.readF(new ByteArrayInputStream(imgData));
于 2013-03-19T13:16:20.110 に答える