Facededetion后OutOfMemoryError

OutOfMemoryError after 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)

你失败的原因是因为使用了图像处理算法。我不确定 openimaj 使用什么,但有两种解决方法:

  1. 增加堆大小,以便您的应用程序有更多内存可用于图像处理。参见 How can I increase the JVM memory?

  2. 减小图像大小,以便您的应用程序使用更少的内存进行处理。

根据我自己在移动设备上进行人脸检测的经验(内存有限),940x720 似乎对人脸检测来说绰绰有余。随意调整为 640x480(或类似),结果应该不会受到影响。

请记住,您可以复制初始图像,以任意纵横比 (i.g.1.5) 调整大小,在新调整大小的图像上检测人脸,return 初始图像检测到的人脸坐标乘以你的纵横比。