Ask Your Question
1

Detect faces on an image in Android OpenCV java

asked 2013-10-12 00:27:24 -0600

Melvin gravatar image

updated 2013-10-13 13:38:47 -0600

When touch on the screen, this method is invoked, highgui.imwrite is suppose to overwrite the previous store into sdcard method.

 public boolean onTouch(View v, MotionEvent event) {
         Log.i(TAG,"onTouch event");

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
     String currentDateandTime = sdf.format(new Date());
     String fileName = Environment.getExternalStorageDirectory().getPath() +
                               "/sample_picture_" + currentDateandTime + ".jpg";
     mOpenCvCameraView.takePicture(fileName);
     Toast.makeText(this, fileName + " saved", Toast.LENGTH_SHORT).show();
  Mat a = Highgui.imread(fileName);

  MatOfRect faceDetections = new MatOfRect();


  if (mDetectorType == JAVA_DETECTOR) {
      if (mJavaDetector != null)
  mJavaDetector.detectMultiScale(a, faceDetections);
  }
  else if (mDetectorType == NATIVE_DETECTOR) {
      if (mNativeDetector != null)
          mNativeDetector.detect(mGray, faceDetections);
  }
  else {
      Log.e(TAG, "Detection method is not selected!");
  }


     for (Rect rect : faceDetections.toArray()){

       Core.rectangle(a, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0));
      Boolean bool = null;
      bool =   Highgui.imwrite(fileName,a);
     if (bool == true)
        Log.d(TAG, "SUCCESS writing image to external storage");
      else
        Log.d(TAG, "Fail writing image to external storage");

    }
    return false;
}

Then this method will create fileName for storing in external storage and takes the picture.

public void takePicture(final String fileName) {
            Log.i(TAG, "Taking picture");
            this.mPictureFileName = fileName;
            // Postview and jpeg are sent in the same buffers if the queue is not empty when performing a capture.
            // Clear up buffers to avoid mCamera.takePicture to be stuck because of a memory issue   

            mCamera.setPreviewCallback(null);

            // PictureCallback is implemented by the current class    

            mCamera.takePicture(null, null, this);        
        }

This method takes bytes array and store into sdcard.

 public void onPictureTaken(byte[] data, Camera camera) {
    Log.i(TAG, "Saving a bitmap to file");
    // The camera preview was automatically stopped. Start it again.
    mCamera.startPreview();

  //...

    mCamera.setPreviewCallback(this);

    // Write the image in a file (in jpeg format)
    try {
        FileOutputStream fos = new FileOutputStream(mPictureFileName);

        fos.write(data);
        fos.close();

    } catch (java.io.IOException e) {
        Log.e("PictureDemo", "Exception in photoCallback", e);
    }



}

There are 2 constructor for the class and the cascade file loaders

public ActivityView(Context context, AttributeSet attrs) {
         super(context, attrs);

         }
    public ActivityView(Context context) {
        super(context, null);
        try {
         // copy the resource into an XML file so that we can create the classifier
         final File cascadeFile = getCascade(R.raw.lbpcascade_frontalface);

        _javaDetector = new CascadeClassifier(cascadeFile.getAbsolutePath());
         if (_javaDetector.empty()) {
         Log.e(TAG, "Failed to load cascade classifier");
         _javaDetector = null;
         } else{
         Log.i(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath());
         }

         _nativeDetector = new DetectionBasedTracker(cascadeFile.getAbsolutePath(), 0);

        cascadeFile.getParentFile().delete();
         cascadeFile.delete();

        } catch (IOException e) {
         e.printStackTrace();
         Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
         }

    }    

        private File getCascade(final int cascadeRessourceId) throws IOException{
         InputStream is = null;
         OutputStream os = null;

         try{
         is = getContext().getResources().openRawResource(cascadeRessourceId);
         File cascadeDir = getContext().getDir("cascade", Context.MODE_PRIVATE);
         File cascadeFile = new File(cascadeDir, "cascade.xml");
         os = new FileOutputStream(cascadeFile);

         byte[] buffer = new byte[4096];
         int bytesRead;
         while ((bytesRead = is.read(buffer)) != -1) {
         os.write(buffer, 0, bytesRead);
         }

         return cascadeFile;
         }finally{
         is.close();
         os.close();
         }
         }

Now I believe I have converted to type Mat with highgui.imread(directory). But now I want to able to detect faces ... (more)

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2013-10-12 01:34:40 -0600

Daniil Osokin gravatar image

Hi Melvin, looks like you save wrong Mat: you've drawn rectangles on a, but saves newImage.

edit flag offensive delete link more

Comments

Thanks Daniil, I didn't notice that. I changed it to Mat a, but It still not showing the rect. I'm not sure whats wrong. I modified a little by putting the detection inside onTouch method. Please take a look, If there is any problem. Thanks again.

Melvin gravatar imageMelvin ( 2013-10-12 05:13:06 -0600 )edit

Have you any found regions?

Daniil Osokin gravatar imageDaniil Osokin ( 2013-10-12 16:15:27 -0600 )edit

for (Rect rect : faceDetections.toArray()){ Core.rectangle(a, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0)); } this is suppose to draw circle on the detected faces. It worked on my opencv with java desktop. But my problem now is that highgui.imwrite does not write the image file into the sdcard.

Melvin gravatar imageMelvin ( 2013-10-13 01:42:35 -0600 )edit

Try to see in debug, what mat comes to imwrite. I've tried to draw with Core.rectange() a rect and then save this Mat through imwrite and everything works fine. BTW, takePicture is async, so it's not correct to read "saved" image right after takePicture call. Suggest to move this part of code back, inside onPictureTaken.

Daniil Osokin gravatar imageDaniil Osokin ( 2013-10-13 05:11:55 -0600 )edit

I have checked the logcat and It says detection method is not selected. There must be something wrong with loading the cascade file. I also manage to check the imwrite when converting the img to graysacle and its worked fine. I uploaded my code for loading cascade file please take a look. Much appreciated.

Melvin gravatar imageMelvin ( 2013-10-13 13:09:26 -0600 )edit

mNativeDetector.detect(mGray, faceDetections);

getting error:: The method detect(Mat, MatOfRect) is undefined for the type DetectionBasedTracker

Please help. Thank you!

VPallavi gravatar imageVPallavi ( 2015-06-25 02:41:09 -0600 )edit

Hello, have you been able to detect a saved image on sdcard? Because I'm trying many ways and I could not.

Josival gravatar imageJosival ( 2017-04-30 08:46:05 -0600 )edit

Question Tools

Stats

Asked: 2013-10-12 00:27:24 -0600

Seen: 3,342 times

Last updated: Oct 13 '13