OutOfMemoryError после Facededetion

package facerec;


import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import org.openimaj.feature.DoubleFVComparison;
import org.openimaj.image.FImage;
import org.openimaj.image.MBFImage;
import org.openimaj.image.colour.RGBColour;
import org.openimaj.image.processing.face.alignment.RotateScaleAligner;
import org.openimaj.image.processing.face.detection.HaarCascadeDetector;
import org.openimaj.image.processing.face.detection.keypoints.FKEFaceDetector;
import org.openimaj.image.processing.face.detection.keypoints.KEDetectedFace;
import org.openimaj.image.processing.face.recognition.EigenFaceRecogniser;
import org.openimaj.image.processing.face.recognition.FaceRecognitionEngine;
import org.openimaj.image.typography.hershey.HersheyFont;
import org.openimaj.math.geometry.point.Point2d;
import org.openimaj.ml.annotation.Annotated;
import org.openimaj.ml.annotation.AnnotatedObject;
import org.openimaj.ml.annotation.ScoredAnnotation;
import org.openimaj.util.pair.IndependentPair;
import org.openimaj.video.VideoDisplay;
import org.openimaj.video.VideoDisplayListener;
import org.openimaj.video.capture.VideoCapture;


public class NewFaceRegister extends KeyAdapter implements VideoDisplayListener<MBFImage> {
    private VideoCapture capture;
    private VideoDisplay<MBFImage> videoFrame;

    FKEFaceDetector faceDetector = new FKEFaceDetector(new HaarCascadeDetector());
    private EigenFaceRecogniser<KEDetectedFace, String> recogniser = EigenFaceRecogniser.create(20, new RotateScaleAligner(), 1, DoubleFVComparison.CORRELATION, 0.9f);
    FaceRecognitionEngine<KEDetectedFace, String> engine = FaceRecognitionEngine.create(faceDetector, recogniser);
    Annotated<KEDetectedFace, String> faceobj;
    private FImage currentFrame;

    public NewFaceRegister() throws Exception {
        capture = new VideoCapture(940, 720);
        //engine = new CLMFaceTracker();
        //engine.fpd = 120;

        videoFrame = VideoDisplay.createVideoDisplay(capture);
        videoFrame.addVideoListener(this);
        SwingUtilities.getRoot(videoFrame.getScreen()).addKeyListener(this);
}

    @Override
    public synchronized void keyPressed(KeyEvent key) {
        if (key.getKeyCode() == KeyEvent.VK_SPACE) {
            this.videoFrame.togglePause();
        } else if (key.getKeyChar() == 'c') {
            // if (!this.videoFrame.isPaused())
            // this.videoFrame.togglePause();

            final String person = JOptionPane.showInputDialog(this.videoFrame.getScreen(), "Name der Person eingeben", "",
                    JOptionPane.QUESTION_MESSAGE);

            final List<KEDetectedFace> faces = detectFaces();
            if (faces.size() == 1) {
                engine.train(faces.get(0), person);
                //TODO Datenbankmethode aufrufen, welches das AnnotatedObject (faceObj) speichert.
            } else {
                System.out.println("Zu viele/wenige Gesichter im Bild");
            }

            //this.videoFrame.close();
        } else 
            System.out.println("Wrong key");
    }

    private List<KEDetectedFace> detectFaces() {
        return engine.getDetector().detectFaces(currentFrame);
    }

    @Override
    public void afterUpdate(VideoDisplay<MBFImage> display) {
        // do nothing
    }

    @Override
    public synchronized void beforeUpdate(MBFImage frame) {
        this.currentFrame = frame.flatten();
        /*engine.track(frame);
        engine.drawModel(frame, true, true, true, true, true);*/
        final List<KEDetectedFace> faces = detectFaces();
        for (KEDetectedFace face : faces) {
            frame.drawShape(face.getBounds(), RGBColour.RED);
        }

        if (recogniser != null && recogniser.listPeople().size() >= 1) {
            for (KEDetectedFace face : faces) {
                List<IndependentPair<KEDetectedFace, ScoredAnnotation<String>>> name = engine.recogniseBest(face.getFacePatch());

                if (name.size() > 0) {
                    final Point2d r = face.getBounds().getTopLeft();
                    frame.drawText(name.get(0).getSecondObject().toString(), r, HersheyFont.ROMAN_SIMPLEX, 15, RGBColour.GREEN);
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        new NewFaceRegister();
    }
}

Почему я получаю ошибку OutOfMemoryError? Я попробовал это с другим Dedector, и там это работает?! Я также искал в некоторых других Вопросах Ответ, и я нашел одно Решение, и я точно работал с ним, но он также не работал. Я впервые работаю с Openimaj.

Exception in thread "Thread-4" java.lang.OutOfMemoryError: Java heap space
at no.uib.cipr.matrix.AbstractDenseMatrix.<init>(AbstractDenseMatrix.java:47)
at no.uib.cipr.matrix.DenseMatrix.<init>(DenseMatrix.java:167)
at no.uib.cipr.matrix.SVD.<init>(SVD.java:98)
at no.uib.cipr.matrix.SVD.<init>(SVD.java:75)
at no.uib.cipr.matrix.SVD.factorize(SVD.java:146)
at org.openimaj.math.matrix.ThinSingularValueDecomposition.<init>(ThinSingularValueDecomposition.java:84)
at org.openimaj.math.matrix.ThinSingularValueDecomposition.<init>(ThinSingularValueDecomposition.java:69)
at org.openimaj.math.matrix.algorithm.pca.ThinSvdPrincipalComponentAnalysis.learnBasisNorm(ThinSvdPrincipalComponentAnalysis.java:56)
at org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis.learnBasis(PrincipalComponentAnalysis.java:183)
at org.openimaj.math.matrix.algorithm.pca.PrincipalComponentAnalysis.learnBasis(PrincipalComponentAnalysis.java:170)
at org.openimaj.ml.pca.FeatureVectorPCA.learnBasis(FeatureVectorPCA.java:113)
at org.openimaj.image.model.EigenImages.train(EigenImages.java:125)
at org.openimaj.image.processing.face.feature.EigenFaceFeature$Extractor.train(EigenFaceFeature.java:167)
at org.openimaj.image.processing.face.recognition.EigenFaceRecogniser.beforeBatchTrain(EigenFaceRecogniser.java:159)
at org.openimaj.image.processing.face.recognition.LazyFaceRecogniser.retrain(LazyFaceRecogniser.java:139)
at org.openimaj.image.processing.face.recognition.LazyFaceRecogniser.annotate(LazyFaceRecogniser.java:153)
at org.openimaj.image.processing.face.recognition.EigenFaceRecogniser.annotate(EigenFaceRecogniser.java:55)
at org.openimaj.image.processing.face.recognition.FaceRecogniser.annotateBest(FaceRecogniser.java:115)
at org.openimaj.image.processing.face.recognition.FaceRecognitionEngine.recogniseBest(FaceRecognitionEngine.java:260)
at facerec.NewFaceRegister.beforeUpdate(NewFaceRegister.java:97)
at facerec.NewFaceRegister.beforeUpdate(NewFaceRegister.java:1)
at org.openimaj.video.VideoDisplay.fireBeforeUpdate(VideoDisplay.java:785)
at org.openimaj.video.VideoDisplay.run(VideoDisplay.java:522)
at java.lang.Thread.run(Unknown Source)

1 ответ

Решение

Причина, по которой вы получили ошибку, в том, что используется алгоритм обработки изображений. Я не уверен что openimaj использует, но для этого есть два возможных решения:

  1. Увеличьте размер кучи, чтобы у вашего приложения было больше памяти для обработки изображений. См. Как я могу увеличить память JVM?

  2. Уменьшите размер изображения, чтобы ваше приложение использовало меньше памяти для обработки.

Основываясь на моем собственном опыте с распознаванием лиц на мобильных устройствах (в том числе и с ограниченной памятью), 940x720 кажется более чем достаточным для распознавания лиц. Не стесняйтесь изменять размер до 640x480 (или аналогичный), результаты не должны быть затронуты.

Помните, что вы можете скопировать исходное изображение, изменить его размер с любым соотношением сторон (ig 1.5), определить лицо на новом измененном изображении и вернуть исходное изображение с обнаруженными координатами лица, умноженными на ваше соотношение сторон.

Другие вопросы по тегам