Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the correct way to implement Tap To Focus for camera?

I'm working on an app which has a custom camera screen, for which I'm supposed to implement tap to focus, like in the Android(more specifically, the Galaxy S4) camera app.

I've tried using the steps outlined here, but it doesn't seem to cause any noticeable focusing. The Focus Mode is set to Continuous Picture(we are supporting only a specific device).

When the user taps on the camera preview, I need to be focusing on the top half of the image. For this, I use the code snippet

Parameters parameters = mCamera.getParameters();  if (parameters.getMaxNumFocusAreas() > 0) {      ArrayList<Area> focusAreas = new ArrayList<Camera.Area>(1);     focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750));      parameters.setFocusAreas(focusAreas);     mCamera.setParameters(parameters); } 

I do NOT want AutoFocus as it takes too long to focus on the image. I am interested only in the top half of the image. Has anybody successfully implemented Tap to Focus along with Continuous Picture mode?

like image 404
Vinay S Shenoy Avatar asked Aug 01 '13 12:08

Vinay S Shenoy


People also ask

How do you tap to focus?

And with a smartphone camera it couldn't be simpler to do. Using the built-in camera app on either an Android device (running 4.0 or later) or a recent iPhone, just tap the screen to specify where the camera should acquire focus. An autofocus square will appear for a moment onscreen at the location you tapped.

What is the proper procedure to manually focus a video camera?

Make sure the camera is set to manual focus. Zoom in as tight as you can on the subject you wish to focus on. Adjust the focus ring until the picture is sharp. Turn the ring clockwise for closer focus, anti-clockwise for more distant focus.

How do I set my camera focus?

Flip the switch on your lens to "MF." Check the side of your DSLR (digital single-lens reflex) or SLR lens for a small switch labeled "AF - MF" or "A - M." If the switch is set to "AF," or automatic focus," flip it to "MF," or manual focus.


2 Answers

Bumped into this issue recently. As MatheusJardimB said, this question helps a lot.

However, in my case, I wanted to start in the ContinuousPicture mode then be able to tap to focus and then continue with the ContinuousPicture mode.

I managed to get it to work by using the onAutoFocus method of the Camera.AutoFocusCallback(). I'm not sure if it's the best or the prettiest way of doing it, but it seems to work.

Here's the code:

setOnTouchListener(new View.OnTouchListener() {              @Override         public boolean onTouch(View v, MotionEvent event) {             if (mCamera != null) {                 Camera camera = mCamera.getCamera();                 camera.cancelAutoFocus();                 Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);                  Parameters parameters = camera.getParameters();                 parameters.setFocusMode(Parameters.FOCUS_MODE_MACRO);                  if (parameters.getMaxNumFocusAreas() > 0) {                     List<Area> mylist = new ArrayList<Area>();                     mylist.add(new Camera.Area(focusRect, 1000));                     parameters.setFocusAreas(mylist);                 }                  camera.setParameters(parameters);                 camera.autoFocus(new Camera.AutoFocusCallback() {                                        @Override                     public void onAutoFocus(boolean success, Camera camera) {                         camera.cancelAutoFocus();                         Parameters params = camera.getParameters();                         if (!params.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {                             params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);                             camera.setParameters(params);                         }                     }                 });             }             return true;         }         return false;     }); 

You could just change the focus area to

ArrayList<Area> focusAreas = new ArrayList<Camera.Area>(1); focusAreas.add(new Area(new Rect(-1000, -1000, 1000, 0), 750)); 

and it should work.

UPDATE

I recently acquired a Samsung S5 and tested this out on it. It didn't work that well, so I added a few modifications and it's working now. This was also successfully tested on the Galaxy S6 and Galaxy Note4.

Here's the modified code:

setOnTouchListener(new View.OnTouchListener() {     @Override     public boolean onTouch(View v, MotionEvent event) {         if (mCamera != null) {             Camera camera = mCamera.getCamera();             camera.cancelAutoFocus();             Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);              Parameters parameters = camera.getParameters();             if (parameters.getFocusMode().equals(                     Camera.Parameters.FOCUS_MODE_AUTO) {                 parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);             }              if (parameters.getMaxNumFocusAreas() > 0) {                 List<Area> mylist = new ArrayList<Area>();                 mylist.add(new Camera.Area(focusRect, 1000));                 parameters.setFocusAreas(mylist);             }              try {                 camera.cancelAutoFocus();                 camera.setParameters(parameters);                 camera.startPreview();                 camera.autoFocus(new Camera.AutoFocusCallback() {                     @Override                     public void onAutoFocus(boolean success, Camera camera) {                         if (!camera.getParameters().getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {                             Parameters parameters = camera.getParameters();                             parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);                             if (parameters.getMaxNumFocusAreas() > 0) {                                 parameters.setFocusAreas(null);                             }                             camera.setParameters(parameters);                             camera.startPreview();                         }                     }                 });             } catch (Exception e) {                 e.printStackTrace();             }         }         return true;     } }); 
like image 138
Dude Avatar answered Sep 26 '22 10:09

Dude


this has the solution. I just added the implementation of some missing methods in his code.

private static  final int FOCUS_AREA_SIZE= 300; 

//

mCameraPreview.setOnTouchListener(new View.OnTouchListener() {         @Override         public boolean onTouch(View v, MotionEvent event) {             if (event.getAction() == MotionEvent.ACTION_DOWN) {                 focusOnTouch(event);             }             return true;         }     }); 

//

 private void focusOnTouch(MotionEvent event) {     if (mCamera != null ) {          Camera.Parameters parameters = mCamera.getParameters();         if (parameters.getMaxNumMeteringAreas() > 0){             Log.i(TAG,"fancy !");             Rect rect = calculateFocusArea(event.getX(), event.getY());              parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);             List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();             meteringAreas.add(new Camera.Area(rect, 800));             parameters.setFocusAreas(meteringAreas);              mCamera.setParameters(parameters);             mCamera.autoFocus(mAutoFocusTakePictureCallback);         }else {             mCamera.autoFocus(mAutoFocusTakePictureCallback);         }     } }  private Rect calculateFocusArea(float x, float y) {     int left = clamp(Float.valueOf((x / mCameraPreview.getWidth()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE);     int top = clamp(Float.valueOf((y / mCameraPreview.getHeight()) * 2000 - 1000).intValue(), FOCUS_AREA_SIZE);      return new Rect(left, top, left + FOCUS_AREA_SIZE, top + FOCUS_AREA_SIZE); }  private int clamp(int touchCoordinateInCameraReper, int focusAreaSize) {     int result;     if (Math.abs(touchCoordinateInCameraReper)+focusAreaSize/2>1000){         if (touchCoordinateInCameraReper>0){             result = 1000 - focusAreaSize/2;         } else {             result = -1000 + focusAreaSize/2;         }     } else{          result = touchCoordinateInCameraReper - focusAreaSize/2;     }     return result; } 

// implement this callback to trigger the focus.

private Camera.AutoFocusCallback mAutoFocusTakePictureCallback = new Camera.AutoFocusCallback() {         @Override         public void onAutoFocus(boolean success, Camera camera) {             if (success) {                 // do something...                 Log.i("tap_to_focus","success!");             } else {                 // do something...                 Log.i("tap_to_focus","fail!");             }         }     }; 
like image 29
ahmed_khan_89 Avatar answered Sep 24 '22 10:09

ahmed_khan_89