Подтвердить что ты не робот

Нестабильное распознавание лиц с использованием OpenCV

Im разрабатывает приложение для Android для распознавания лиц, используя JavaCV, который является неофициальной оболочкой OpenCV. После импорта com.googlecode.javacv.cpp.opencv_contrib.FaceRecognizer, Я применяю и тестирую следующие известные методы:

  • LBPH с использованием метода createLBPHFaceRecognizer()
  • FisherFace с использованием метода createFisherFaceRecognizer()
  • EigenFace с использованием метода createEigenFaceRecognizer()

Прежде чем распознать обнаруженное лицо, я исправлю повернутое лицо и обрезаю нужную зону, вдохновляя этот метод

В общем, когда я пропускаю камеру, в базе данных уже существует лицо, распознавание в порядке. Но это не всегда правильно. Иногда он с большой вероятностью распознает неизвестное лицо (не найдено в базе данных обученных образцов). Когда у нас в БД два или более лица сходных черт (борода, усы, очки...), распознавание может быть очень ошибочным между этими лицами!

Чтобы предсказать результат с использованием изображения тестового лица, я применяю следующий код:

public String predict(Mat m) {

        int n[] = new int[1];
        double p[] = new double[1];
        IplImage ipl = MatToIplImage(m,WIDTH, HEIGHT);

        faceRecognizer.predict(ipl, n, p);

        if (n[0]!=-1)
         mProb=(int)p[0];
        else
            mProb=-1;
            if (n[0] != -1)
            return labelsFile.get(n[0]);
        else
            return "Unkown";
    }

Я не могу контролировать порог вероятности p, потому что:

  • Маленький p < 50 может предсказать правильный результат.
  • Высокий p > 70 может предсказать ложный результат.
  • Среднее значение p может предсказать правильное или ложное.

Кроме того, я не понимаю, почему функция прогноза() дает когда-то вероятность более 100 в случае использования LBPH??? и в случае Фишера и Эйгена он дает очень большие значения ( > 2000)? Может ли кто-нибудь помочь найти решение этих странных проблем? Есть ли какие-либо предложения по повышению надежности распознавания? особенно в случае сходства двух разных лиц.

Ниже приведен весь класс, используя Facerecognizer:

package org.opencv.javacv.facerecognition;

import static  com.googlecode.javacv.cpp.opencv_highgui.*;
import static  com.googlecode.javacv.cpp.opencv_core.*;

import static  com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_contrib.*;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.ArrayList;

import org.opencv.android.Utils;
import org.opencv.core.Mat;

import com.googlecode.javacv.cpp.opencv_imgproc;
import com.googlecode.javacv.cpp.opencv_contrib.FaceRecognizer;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.googlecode.javacv.cpp.opencv_core.MatVector;

import android.graphics.Bitmap;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

public  class PersonRecognizer {

    public final static int MAXIMG = 100;
    FaceRecognizer faceRecognizer;
    String mPath;
    int count=0;
    labels labelsFile;

     static  final int WIDTH= 128;
     static  final int HEIGHT= 128;;
     private int mProb=999;


    PersonRecognizer(String path)
    {
      faceRecognizer =  com.googlecode.javacv.cpp.opencv_contrib.createLBPHFaceRecognizer(2,8,8,8,200);
     // path=Environment.getExternalStorageDirectory()+"/facerecog/faces/";
     mPath=path;
     labelsFile= new labels(mPath);


    }

    void changeRecognizer(int nRec)
    {
        switch(nRec) {
        case 0: faceRecognizer = com.googlecode.javacv.cpp.opencv_contrib.createLBPHFaceRecognizer(1,8,8,8,100);
                break;
        case 1: faceRecognizer = com.googlecode.javacv.cpp.opencv_contrib.createFisherFaceRecognizer();
                break;
        case 2: faceRecognizer = com.googlecode.javacv.cpp.opencv_contrib.createEigenFaceRecognizer();
                break;
        }
        train();

    }

    void add(Mat m, String description) {
        Bitmap bmp= Bitmap.createBitmap(m.width(), m.height(), Bitmap.Config.ARGB_8888);

        Utils.matToBitmap(m,bmp);
        bmp= Bitmap.createScaledBitmap(bmp, WIDTH, HEIGHT, false);

        FileOutputStream f;
        try {
            f = new FileOutputStream(mPath+description+"-"+count+".jpg",true);
            count++;
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, f);
            f.close();

        } catch (Exception e) {
            Log.e("error",e.getCause()+" "+e.getMessage());
            e.printStackTrace();

        }
    }

    public boolean train() {

        File root = new File(mPath);
        Log.i("mPath",mPath);
        FilenameFilter pngFilter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith(".jpg");

        };
        };

        File[] imageFiles = root.listFiles(pngFilter);

        MatVector images = new MatVector(imageFiles.length);

        int[] labels = new int[imageFiles.length];

        int counter = 0;
        int label;

        IplImage img=null;
        IplImage grayImg;

        int i1=mPath.length();


        for (File image : imageFiles) {
            String p = image.getAbsolutePath();
            img = cvLoadImage(p);

            if (img==null)
                Log.e("Error","Error cVLoadImage");
            Log.i("image",p);

            int i2=p.lastIndexOf("-");
            int i3=p.lastIndexOf(".");
            int icount=Integer.parseInt(p.substring(i2+1,i3)); 
            if (count<icount) count++;

            String description=p.substring(i1,i2);

            if (labelsFile.get(description)<0)
                labelsFile.add(description, labelsFile.max()+1);

            label = labelsFile.get(description);

            grayImg = IplImage.create(img.width(), img.height(), IPL_DEPTH_8U, 1);

            cvCvtColor(img, grayImg, CV_BGR2GRAY);

            images.put(counter, grayImg);

            labels[counter] = label;

            counter++;
        }
        if (counter>0)
            if (labelsFile.max()>1)
                faceRecognizer.train(images, labels);
        labelsFile.Save();
    return true;
    }

    public boolean canPredict()
    {
        if (labelsFile.max()>1)
            return true;
        else
            return false;

    }

    public String predict(Mat m) {
        if (!canPredict())
            return "";
        int n[] = new int[1];
        double p[] = new double[1];
        IplImage ipl = MatToIplImage(m,WIDTH, HEIGHT);
//      IplImage ipl = MatToIplImage(m,-1, -1);

        faceRecognizer.predict(ipl, n, p);

        if (n[0]!=-1)
         mProb=(int)p[0];
        else
            mProb=-1;
    //  if ((n[0] != -1)&&(p[0]<95))
        if (n[0] != -1)
            return labelsFile.get(n[0]);
        else
            return "Unkown";
    }




      IplImage MatToIplImage(Mat m,int width,int heigth)
      {


           Bitmap bmp=Bitmap.createBitmap(m.width(), m.height(), Bitmap.Config.ARGB_8888);


           Utils.matToBitmap(m, bmp);
           return BitmapToIplImage(bmp,width, heigth);

      }

    IplImage BitmapToIplImage(Bitmap bmp, int width, int height) {

        if ((width != -1) || (height != -1)) {
            Bitmap bmp2 = Bitmap.createScaledBitmap(bmp, width, height, false);
            bmp = bmp2;
        }

        IplImage image = IplImage.create(bmp.getWidth(), bmp.getHeight(),
                IPL_DEPTH_8U, 4);

        bmp.copyPixelsToBuffer(image.getByteBuffer());

        IplImage grayImg = IplImage.create(image.width(), image.height(),
                IPL_DEPTH_8U, 1);

        cvCvtColor(image, grayImg, opencv_imgproc.CV_BGR2GRAY);

        return grayImg;
    }



    protected void SaveBmp(Bitmap bmp,String path)
      {
            FileOutputStream file;
            try {
                file = new FileOutputStream(path , true);

            bmp.compress(Bitmap.CompressFormat.JPEG,100,file);  
            file.close();
            }
            catch (Exception e) {
                // TODO Auto-generated catch block
                Log.e("",e.getMessage()+e.getCause());
                e.printStackTrace();
            }

      }


    public void load() {
        train();

    }

    public int getProb() {
        // TODO Auto-generated method stub
        return mProb;
    }


}
4b9b3361

Ответ 1

Я думаю, вам нужно внедрить что-то более надежное для изменений освещения. см. Нормализация освещенности в OpenCV

Затем, чтобы управлять сходством между изображениями, возможно, вы можете использовать что-то вроде Основного компонента Analysis.

Ответ 2

Официальная оболочка Java OpenCV не включает методы сопоставления лиц (включает только обнаружение лиц):

  • LBPH с использованием метода createLBPHFaceRecognizer()
  • FisherFace с использованием метода createFisherFaceRecognizer()
  • EigenFace с использованием метода createEigenFaceRecognizer()

Вместо этого вы должны использовать оболочку JavaCV для использования распознавания лиц.

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