2014-01-05 26 views
22

OpenCVの非公式なラッパーであるJavaCVを使用して、顔認識のためのアンドロイドアプリケーションを開発しています。OpenCVを使用した不安定な顔認識

  • LBPH使用createLBPHFaceRecognizer()メソッド
  • FisherFace使用createFisherFaceRecognizer()メソッド
  • 固有顔createEigenFaceRecognizerを使用して()メソッド

com.googlecode.javacv.cpp.opencv_contrib.FaceRecognizer、 をインポートした後、私は、次の既知の方法を適用してテスト検出された顔を認識する前に、回転した顔を修正して適切な領域を切り抜いて、this method

一般的に、私がカメラに乗るとき、顔はすでにデータベースに存在していますが、認識はOKです。しかし、これは必ずしも正しいとは限りません。時には、未知の顔(訓練されたサンプルのデータベースには見つかりません)が高い確率で認識されることがあります。 DBに2つ以上の同様の機能(ひげ、口髭、眼鏡など)の顔があると、顔の認識が間違っている可能性があります。

試験顔画像を使用して結果を予測するために、私は、次のコードを適用する。ので、私は、確率pのしきい値を制御することができない

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 < 50は正しい結果を予測することができた。
  • 高いp> 70は、誤った結果を予測する可能性があります。
  • 中pは、正しいか誤っているかを予測できます。

また、私はpredict()関数がLBPHを使用している場合に100を超える確からしい確率を与える理由を理解していませんか?フィッシャーとエイゲンの場合、それは非常に大きな値を与える(> 2000)? 誰かがこのような奇妙な問題の解決策を見つける手助けをすることができますか? 認識の堅牢性を改善する提案はありますか?特に2つの異なる顔の類似性の場合には、

以下が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; 
    } 


} 
+2

はい、3つの異なる*しきい値は、それぞれの方法ごとに1つずつ必要です。それらのすべての機能スペースが異なるからです。また、予測の 'p'値は確率ではありませんが、テスト画像からdb内の最も近い一致までの距離*(したがって、その逆数)は、[[ 0.001]の範囲である。 – berak

+0

@berak私は、iplimage、int []、double []を予測するために3つのパラメータを渡します。さて、私たちはIplimageを渡し、距離は二倍になりましたが、int []は何ですか?それが表すもの。私はそれを本当に理解していないので、私は1,4,8のようにそれに異なる価値を得ています。 – umerk44

+0

これはあなたの人のIDであるクラスラベルです。あなたはそのコードを書いたのですか? – berak

答えて

0

のOpenCVの公式Javaラッパーは、顔照合方法が含まれていない(のみ顔検出を含む):createLBPHFaceRecognizerを用い

  • LBPH( )メソッド
  • createFisherFaceRecognizer()メソッドを使用するFisherFace
  • createEigenFaceRecognizer()を使用したEigenFaceは、met hod

代わりに、JavaCVラッパーを使用して顔認識を使用する必要があります。

また、効率的な顔認識を行うには、適切なトレーニングデータベースを実行する必要があります。詳細については、thisの便利なチュートリアルを参照してください。

2

私は、照明の変化に対してより頑強にするために何かを実装する必要があると思います。 Illumination normalization in OpenCV

次に、画像間の類似性を管理するために、主成分分析のようなものを使用できます。

+1

なぜ-1、私はあなたに認識を妨げる要因の存在下で認識率を改善するためのいくつかのテクニックを教えました。私は、より堅牢になるために、同様のプロジェクトでそれらを使用し、素晴らしい仕事をしています。 – user3529407

関連する問題