1

I am using Android phone with ICECREAMSANDWICH version. In that, I am checking the face-detection behaviour. Additionally, referring the codes available on google.

During debugging with my phone int getMaxNumDetectedFaces () returns 3. So my phone is supported for this.

Then the following code is not working.

public void onFaceDetection(Face[] faces, Camera face_camera1) {
    // TODO Auto-generated method stub
            if(faces.length>0)
            {
                Log.d("FaceDetection","face detected:" +faces.length + "Face 1 location X:"+faces[0].rect.centerX()+"Y:"+faces[0].rect.centerY());
            }
        }

in this faces.length retruning zero tell some suggestions to solve this error.

Kanwaljit Singh
  • 4,339
  • 2
  • 18
  • 21
Cooldharma06
  • 515
  • 1
  • 6
  • 24

1 Answers1

1

I had work with the FaceDetection some time ago. When I was working on that the onFaceDetection didn't work for me, so,I found another way for work on it.

I worked with PreviewCallback, this method takes each frame and you can use it to recognize faces. The only problem here is the format, the default format is NV21 , and you can change it by setPreviewFormat(int), but that didn't work for me too, so, I had to make de conversion for get a Bitmap type that recives the FaceDetector. Here is my code:

public PreviewCallback mPreviewCallback = new PreviewCallback(){
@Override
public void onPreviewFrame(byte[] data, Camera camera) {

  Camera.Size size = camera.getParameters().getPreviewSize();
   Bitmap mfoto_imm = this.getBitmapFromNV21(data, size.width, size.height, true);  //here I get the Bitmap from getBitmapFromNV21 that is the conversion method    
    Bitmap mfoto= mfoto_imm.copy(Bitmap.Config.RGB_565, true); 
    imagen.setImageBitmap(mfoto);
    int alto= mfoto.getHeight();
    int ancho= mfoto.getWidth();
    int count;

   canvas= new Canvas(mfoto);
       dibujo.setColor(Color.GREEN);
   dibujo.setAntiAlias(true);
   dibujo.setStrokeWidth(8);
   canvas.drawBitmap(mfoto, matrix, dibujo);


    FaceDetector mface= new FaceDetector(ancho,alto,1);
    FaceDetector.Face [] face= new FaceDetector.Face[1];
    count = mface.findFaces(mfoto, face);


     PointF midpoint = new PointF();
     int fpx = 0;
         int fpy = 0;

     if (count > 0) {

face[count-1].getMidPoint(midpoint); // you have to take the last one less 1
         fpx= (int)midpoint.x;    // middle pint of  the face in x.
         fpy= (int)midpoint.y;    // middle point of the face in y.

     }

           canvas.drawCircle(fpx, fpy, 10, dibujo); // here I draw a circle on the middle of the face
     imagen.invalidate();

} }

and here are the conversion methods.

public Bitmap getBitmapFromNV21(byte[] data, int width, int height, boolean rotated) {

      Bitmap bitmap = null;
      int[] pixels = new int[width * height];

      // Conver the  array 
      this.yuv2rgb(pixels, data, width, height, rotated);


      if(rotated)
      {
        bitmap = Bitmap.createBitmap(pixels, height, width, Bitmap.Config.RGB_565);
      }
      else
      {
        bitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.RGB_565);
      }

      return bitmap;
    }


public void yuv2rgb(int[] out, byte[] in, int width, int height, boolean rotated) 
           throws NullPointerException, IllegalArgumentException 
         { 
          final int size = width * height; 


          if(out == null) throw new NullPointerException("buffer 'out' == null"); 
          if(out.length < size) throw new IllegalArgumentException("buffer 'out' length < " + size); 
          if(in == null) throw new NullPointerException("buffer 'in' == null"); 
          if(in.length < (size * 3 / 2)) throw new IllegalArgumentException("buffer 'in' length != " + in.length + " < " + (size * 3/ 2)); 

          // YCrCb
          int Y, Cr = 0, Cb = 0;


          int Rn = 0, Gn = 0, Bn = 0;
          for(int j = 0, pixPtr = 0, cOff0 = size - width; j < height; j++) { 
           if((j & 0x1) == 0)
            cOff0 += width;
           int pixPos = height - 1 - j; 
           for(int i = 0, cOff = cOff0; i < width; i++, cOff++, pixPtr++, pixPos += height) { 

            // Get Y
            Y = 0xff & in[pixPtr]; // 0xff es por el signo

            // Get Cr y Cb
            if((pixPtr & 0x1) == 0) { 
             Cr = in[cOff]; 
             if(Cr < 0) Cr += 127; else Cr -= 128;
             Cb = in[cOff + 1]; 
             if(Cb < 0) Cb += 127; else Cb -= 128; 

             Bn = Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
             Gn = - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5);
             Rn = Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
            } 


            int R = Y + Rn; 
            if(R < 0) R = 0; else if(R > 255) R = 255; 
            int B = Y + Bn; 
            if(B < 0) B = 0; else if(B > 255) B = 255; 
            int G = Y + Gn; 
            if(G < 0) G = 0; else if(G > 255) G = 255; //At this point the code could apply some filter From the separate components of the image.For example, they could swap 2 components or remove one

            int rgb = 0xff000000 | (R << 16) | (G << 8) | B; //Depending on the option the output buffer is filled or not applying the transformation
            if(rotated)
             out[pixPos] = rgb; 
            else
             out[pixPtr] = rgb;
           } 
          } 
         }
};

The setPreviewFormat(int) in some devices doesn't work, but maybe you can try and create the Bitmap without use the conversion. I hope this help you.

Jorge
  • 238
  • 1
  • 10