【问题标题】:Comparing detected face with array of existing faces with opencv in android在android中使用opencv将检测到的人脸与现有人脸数组进行比较
【发布时间】:2015-02-15 17:35:27
【问题描述】:

我正在通过 opencv 制作人脸识别应用程序。我可以检测到人脸,而且资源中的人脸很少。 我在这个地方堆积:

// These vectors hold the images and corresponding labels.
vector<Mat> images;
vector<int> labels;

Mat testSample = images[images.size() - 1];
    int testLabel = labels[labels.size() - 1];
    images.pop_back();
    labels.pop_back();


    Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
    model->train(images, labels);

    string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
    cout << result_message << endl;
    // Here is how to get the eigenvalues of this Eigenfaces model:
    Mat eigenvalues = model->getMat("eigenvalues");
    // And we can do the same to display the Eigenvectors (read Eigenfaces):
    Mat W = model->getMat("eigenvectors");
    // Get the sample mean from the training data
    Mat mean = model->getMat("mean");

请有人解释一下,我应该将检测到的人脸放在哪里以及我将它们与数据库进行比较的位置?我必须把它们都放在这个vector&lt;Mat&gt; images; 中还是什么? 字段vector&lt;int&gt; labels; 也如何工作?我应该在那里写什么? 如果有人可以写信给我简单的例子,那就太好了。检测到我作为参数从 Java 类传递的面孔。

谢谢!

【问题讨论】:

    标签: android c++ opencv java-native-interface face-recognition


    【解决方案1】:

    需要导入javacv库(com.googlecode.javacv.cpp.opencv_contrib.FaceRecognizer)自带的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);
    
        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";
    }
    
      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;
     }
    
    }
    

    【讨论】:

    • 非常感谢您的详细回答,但我正在使用 JNI,我会避免使用 JavaCV...尤其是因为我已经尝试过,但没有任何结果...
    • 你没看过这个教程吗:docs.opencv.org/modules/contrib/doc/facerec/tutorial/…?有详细代码
    • 是的,我正在关注本教程,但我无法理解在本教程中我应用两张图片(从数据库中检测到的面孔和面孔)的位置。只显示了一个名为“images”的 Mat 数组,但我应该把这些“Both”放在那里还是什么?根据这将是使用标签的一个很好的例子......那些只是ID(如来自faces.size的int i)或一些特定名称......我找不到完全评论这部分......
    • 不完全符合您的要求。图像数据库将使用 model->train(images, labels) 进行训练,现在您已经有了一个使用一组人脸训练的模型。任何其他测试人脸(检测到的人脸)将通过调用与数据库匹配:int prediction = model->predict(face_resized);这里的预测是相似度(需要更多关于预测值的阅读)
    • 我想我明白你的意思了。正如我澄清的那样,字段“标签”我可以为每个人简单地填写 0、1、2、3 等,并且 int predictLabel 将包含匹配的图像的这个“id”......我对吗?但是如果图像不匹配怎么办?一定有一定程度的信心......你有没有预测的负面结果?它在说什么?
    【解决方案2】:
    package org.tensorflow.lite.examples.test;
    
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.FilenameFilter;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.opencv.android.Utils;
    import org.opencv.core.CvException;
    import org.opencv.core.CvType;
    import org.opencv.core.Mat;
    import org.opencv.core.Scalar;
    import org.opencv.face.EigenFaceRecognizer;
    import org.opencv.face.FaceRecognizer;
    import org.opencv.face.FisherFaceRecognizer;
    import org.opencv.face.LBPHFaceRecognizer;
    import org.opencv.imgproc.Imgproc;
    
    
    import android.graphics.Bitmap;
    import android.util.Log;
    
    public  class PersonRecognizer {
    
      //  FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(1, 6, 6, 6, 13.5);
    //2,2,12,12,15)
      //  FaceRecognizer faceRecognizer =  FisherFaceRecognizer.create(100,100.0);
     // FaceRecognizer faceRecognizer =  FisherFaceRecognizer.create(0, 123.0);
    
     //   FaceRecognizer faceRecognizer = EigenFaceRecognizer.create(10, 123.0);
    
       // FaceRecognizer faceRecognizer = EigenFaceRecognizer.create(1,190.5);
      // FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(1,8,8,8,123.0)
       FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(2, 8, 8, 8, 64);
    
      //  FaceRecognizer faceRecognizer = LBPHFaceRecognizer.create(2,2,12,12,15);
        String mPath;
        int count=0;
        Labels labelsFile;
    
        static  final int WIDTH= 224;
        static  final int HEIGHT= 224;;
        private int mProb=999;
    
    
        PersonRecognizer(String path) {
            // path=Environment.getExternalStorageDirectory()+"/facerecog/faces/";
            mPath=path;
            labelsFile= new Labels(mPath);
    
    
        }
    
    
        void add(Bitmap m, String description) {
    
            Mat mat = new Mat();
            Utils.bitmapToMat(m, mat);
            Mat mGray = new Mat();
            Imgproc.cvtColor(mat,mGray,Imgproc.COLOR_RGB2GRAY);
    
            Bitmap bmp = null;
            FileOutputStream f;
            Mat tmp = new Mat (HEIGHT, WIDTH, CvType.CV_8U, new Scalar(4));
            try {
                Imgproc.cvtColor(mGray, tmp, Imgproc.COLOR_GRAY2RGBA, 4);
                bmp = Bitmap.createBitmap(tmp.cols(), tmp.rows(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(tmp, bmp);
                f = new FileOutputStream(mPath+description+"-"+count+".jpg",true);
                count++;
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, f);
                f.close();
            }
            catch (CvException e) {
                Log.d("Exception",e.getMessage());
            }
            catch (Exception e) {
                Log.e("error908",e.getCause()+" "+e.getMessage());
                e.printStackTrace();
            }
    
        }
    
        public boolean train() {
    
            File root = new File(mPath);
    
            FilenameFilter pngFilter = new FilenameFilter() {
                public boolean accept(File dir, String name) {
    
                    return name.toLowerCase().endsWith(".jpg");
                };
            };
    
            File[] imageFiles = root.listFiles(pngFilter);
    
            List<Mat> images = new ArrayList<>();
    
            int[] labels = new int[imageFiles.length];
    
            int counter = 0;
            int label;
    
            int i1=mPath.length();
            for (File image : imageFiles) {
                Log.d("TAG11", "train: collecting");
                String p = image.getAbsolutePath();
    
                Mat imagexnm = org.opencv.imgcodecs.Imgcodecs.imread(p, 0);
    
                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)
                    Log.d("TAG11", "train: add label");
                    labelsFile.add(description, labelsFile.max()+1);
    
                label = labelsFile.get(description);
    
    
    
                images.add(imagexnm);
    
                labels[counter] = label;
    
    
    
                counter++;
            }
            if (counter>0)
                if (labelsFile.max()>1)
                {
                    Mat labelsmat = new Mat(labels.length, 1, CvType.CV_32SC1);
                    for(int i=0;i<labels.length;i++)
                    {
                        labelsmat.put(i,0,labels[i]);
                    }
    
                    faceRecognizer.train(images, labelsmat);
                    labelsFile.Save();
                }
    
    
            return true;
        }
    
        public boolean canPredict()
        {
            if (labelsFile.max()>1)
                return true;
            else
                return false;
    
        }
    
        public String predict(Bitmap m) {
            if (!canPredict())
                return "-1";
            int n[] = new int[1];
            double p[] = new double[1];
    
    
    
            Mat mat = new Mat();
            Utils.bitmapToMat(m, mat);
            Mat mGray = new Mat();
            Imgproc.cvtColor(mat,mGray,Imgproc.COLOR_RGB2GRAY);
            faceRecognizer.predict(mGray, 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 "Unknown";
        }
    
    
    
    
    
    
    
        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;
        }
    
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-18
      • 2013-09-02
      • 2017-08-28
      • 2013-03-23
      • 2017-10-02
      • 2012-03-08
      • 2019-12-01
      • 2013-09-24
      相关资源
      最近更新 更多