Ask Your Question
3

ANDROID: Use autofocus with CameraBridgeViewBase?

asked 2013-08-29 07:14:17 -0600

Max Muster gravatar image

updated 2013-08-29 08:15:30 -0600

hello there. im writing an android app and im using the CameraBridgeViewBase just like in the facedetection-example that comes with openCV. Here is a part of my code, just basic initialisation:

private CameraBridgeViewBase mOpenCvCameraView;

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.activity_main);

    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial1_activity_java_surface_view);
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
}

everything works fine, except that the frames it takes are blurry and not sharp. i wanted to use something like auotfocus, but i found that the CameraBridgeViewBase class does not offer that.

is there a way to use any type of focus with this class? or is there any other way to capture sharper frames with the CameraBridgeViewBase?

thanks in advance :)

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
5

answered 2013-08-30 04:22:44 -0600

Moster gravatar image

updated 2013-08-30 04:49:35 -0600

Ok, same stuff, just with JavaCameraView:

activity:

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;

import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.WindowManager;
import android.widget.Toast;

public class test extends Activity implements CvCameraViewListener2 {
private static final String TAG = "test";

private JavaCamResView mOpenCvCameraView;
private List<Camera.Size> mResolutionList;

private MenuItem[] mResolutionMenuItems;
private MenuItem[] mFocusListItems;
private MenuItem[] mFlashListItems;

private SubMenu mResolutionMenu;
private SubMenu mFocusMenu;
private SubMenu mFlashMenu;



private Mat mGrayMat;

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");                    
                mOpenCvCameraView.enableView();                  

            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

public test() {
    Log.i(TAG, "Instantiated new " + this.getClass());
}

@Override
public void onCreate(Bundle savedInstanceState) {

    Log.i(TAG, "called onCreate");
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.java_cam_res_view);

    mOpenCvCameraView = (JavaCamResView) findViewById(R.id.test_view);
    mOpenCvCameraView.setCvCameraViewListener(this); 

}

@Override
public void onPause()
{
    super.onPause();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

@Override
public void onResume()
{
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this, mLoaderCallback);


}

public void onDestroy() {
    super.onDestroy();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

public void onCameraViewStarted(int width, int height) {        

    mGrayMat = new Mat(height, width, CvType.CV_8UC1);

}

public void onCameraViewStopped() { 
    mGrayMat.release();
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    mGrayMat=inputFrame.gray();        
    return mGrayMat;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    List<String> mFocusList = new LinkedList<String>();
    int idx =0;

    mFocusMenu = menu.addSubMenu("Focus");

    mFocusList.add("Auto");
    mFocusList.add("Continuous Video");
    mFocusList.add("EDOF");
    mFocusList.add("Fixed");
    mFocusList.add("Infinity");
    mFocusList.add("Makro");
    mFocusList.add("Continuous Picture");

    mFocusListItems = new MenuItem[mFocusList.size()];

    ListIterator<String> FocusItr = mFocusList.listIterator();
    while(FocusItr.hasNext()){
        // add the element to the mDetectorMenu submenu
        String element = FocusItr.next();
        mFocusListItems[idx] = mFocusMenu.add(2,idx,Menu.NONE,element);
        idx++;
    }



    List<String> mFlashList = new LinkedList<String>();
    idx = 0;

    mFlashMenu = menu.addSubMenu("Flash");

    mFlashList.add("Auto");
    mFlashList.add("Off");
    mFlashList.add("On");
    mFlashList.add("Red-Eye");
    mFlashList.add("Torch");

    mFlashListItems = new MenuItem[mFlashList.size()];

    ListIterator<String> FlashItr = mFlashList.listIterator();
    while(FlashItr.hasNext()){
        // add the element to the mDetectorMenu submenu
        String element = FlashItr.next();
        mFlashListItems[idx] = mFlashMenu.add(3,idx,Menu.NONE,element);
        idx++;
    }



    mResolutionMenu = menu.addSubMenu("Resolution");
    mResolutionList = mOpenCvCameraView.getResolutionList();
    mResolutionMenuItems = new MenuItem[mResolutionList.size()];

    ListIterator<Camera.Size> resolutionItr = mResolutionList.listIterator();
    idx = 0;
    while(resolutionItr.hasNext()) {
        Camera.Size element = resolutionItr.next();
        mResolutionMenuItems[idx] = mResolutionMenu.add(1, idx, Menu.NONE,
                Integer.valueOf((int) element.width).toString() + "x" + Integer.valueOf((int) element.height).toString());
        idx++;
     }

    return true;
}

public boolean onOptionsItemSelected(MenuItem item) {
    Log.e(TAG, "called onOptionsItemSelected; selected item: " + item);
   if (item.getGroupId() == 1)
    {
        int id = item.getItemId();
        Camera.Size resolution = mResolutionList.get(id);
        mOpenCvCameraView.setResolution(resolution);
        resolution = mOpenCvCameraView.getResolution();
        Log.e("test","test");
        String caption = Integer.valueOf((int) resolution ...
(more)
edit flag offensive delete link more

Comments

1

I have edited the Activity and View a little bit. Now there should be a toast on the screen in case a focus or flash mode is not supported. For example my tablet has no EDOF focus mode and no red_eye flash mode.

Moster gravatar imageMoster ( 2013-08-30 04:51:43 -0600 )edit

@Moster thanks for your reply, i really apprechiate your effort to help me. nevertheless, i copied all of your new code and built the app. i tried each of the focus modes, some were not supported just as you said. sadly none of the focus modes made my frames any sharper, they still look the same. i guess the code you posted makes the frames sharper / focussed on your device though? im currently using an htc desire hd. i made a test project where i just instantiated a normal Camera object and made it autofocus when i clicked on it (using the Camera.autofocus() method) and this works just fine, so im sure my device should be able to handle focussing. i really dont know whats wrong here...

Max Muster gravatar imageMax Muster ( 2013-08-30 05:35:07 -0600 )edit
1

I have a asus tf700t tablet for testing. When I choose Continuous Video it automatically adjusts the focus. This works till approximately 5-10cm away from an object. So I really dont know what might be the issue.

Moster gravatar imageMoster ( 2013-08-30 05:43:31 -0600 )edit

@Moster the Continuous Video Focus is one of them which are not available on my device. Does any of the other focus modes achieve the same result for you?

Max Muster gravatar imageMax Muster ( 2013-08-30 05:44:45 -0600 )edit

Which android version do you have on your desire hd?

Moster gravatar imageMoster ( 2013-08-30 05:53:11 -0600 )edit

Android 2.3.5 is running on this device.

Max Muster gravatar imageMax Muster ( 2013-08-30 05:54:28 -0600 )edit
1

Does the standard android camera app have autofocous? I mean, there's a difference between touch2focus and autofocus. One could work, the other not. I have checked xda-developers.com and some other people also reported auto-focus issues on the Desire HD.

Moster gravatar imageMoster ( 2013-08-30 06:02:46 -0600 )edit

@Moster yes, my standard camera app has autofocus. when i use it and go near an object and it is blurred, then it takes a very short moment an focusses on the object without me having to tap on the screen.

Max Muster gravatar imageMax Muster ( 2013-08-30 06:10:07 -0600 )edit
1

Could you try this please, change the focus mode to fixed. Then go close to some object like a paper with text or monitor, it should be blurred of course. Then enable continuous mode and tell me if it at least changes a bit.

Last thing I could imagine is that Htc has some strange implementation of the camera api. so that opencv is not working correctly. But then it doesnt make sense that it does not return "Mode not supported".

Moster gravatar imageMoster ( 2013-08-30 06:17:14 -0600 )edit

@Moster the fixed mode is not available either :D full list of not supported modes: Continuous Video, EDOF, Fixed, Makro. I can only select the rest of the modes without getting a toast saying "not supportet".

Max Muster gravatar imageMax Muster ( 2013-08-30 06:34:35 -0600 )edit
5

answered 2013-08-29 08:54:58 -0600

Moster gravatar image

updated 2013-08-30 02:57:06 -0600

Yes, it is possible to set the focus mode. I have a little test project that does this. Its important that you actually base the whole thing on a NativeCameraView, since that use the VideoCapture class which holds a set function for several camera features. The basic camera class is this:

package org.opencv.samples.test;

import java.util.List;

import org.opencv.android.NativeCameraView;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;

import android.content.Context;
import android.util.AttributeSet;

public class NativeCamResView extends NativeCameraView {

public NativeCamResView(Context context, AttributeSet attrs) {
    super(context, attrs);
} 

public List<Size> getResolutionList() {     
    return mCamera.getSupportedPreviewSizes();        
}

public void setResolution(Size resolution) {
    disconnectCamera();
    connectCamera((int)resolution.width, (int)resolution.height);       
}

public void setFocusMode (int type){
    switch (type){
    case 0:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_AUTO);
        break;
    case 1:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_CONTINUOUS_VIDEO);
        break;
    case 2:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_EDOF);
        break;
    case 3:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_FIXED);
        break;
    case 4:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_INFINITY);
        break;
    case 5:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FOCUS_MODE, Highgui.CV_CAP_ANDROID_FOCUS_MODE_MACRO);
        break;
    }
}   

public void setFlashMode (int type){
    switch (type){
    case 0:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE, Highgui.CV_CAP_ANDROID_FLASH_MODE_AUTO);
        break;
    case 1:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE, Highgui.CV_CAP_ANDROID_FLASH_MODE_OFF);
        break;
    case 2:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE, Highgui.CV_CAP_ANDROID_FLASH_MODE_ON);
        break;
    case 3:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE, Highgui.CV_CAP_ANDROID_FLASH_MODE_RED_EYE);
        break;
    case 4:
        mCamera.set(Highgui.CV_CAP_PROP_ANDROID_FLASH_MODE, Highgui.CV_CAP_ANDROID_FLASH_MODE_TORCH);
        break;
    }
}   

public Size getResolution() {
    Size s = new Size(mCamera.get(Highgui.CV_CAP_PROP_FRAME_WIDTH),mCamera.get(Highgui.CV_CAP_PROP_FRAME_HEIGHT));
    return s;
}
}

Then youractivity should could look like this:

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.WindowManager;
import android.widget.Toast;

public class test extends Activity implements CvCameraViewListener2 {
private static final String TAG = "test";

private NativeCamResView mOpenCvCameraView;
private List<Size> mResolutionList;

private MenuItem[] mResolutionMenuItems;
private MenuItem[] mFocusListItems;
private MenuItem[] mFlashListItems;

private SubMenu mResolutionMenu;
private SubMenu mFocusMenu;
private SubMenu mFlashMenu;



private Mat mGrayMat;

private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");                    
                mOpenCvCameraView.enableView();                  

            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

public test() {
    Log.i(TAG, "Instantiated new " + this.getClass());
}

@Override
public void onCreate(Bundle savedInstanceState) {

    Log.i(TAG, "called onCreate");
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    setContentView(R.layout.native_cam_res_view);

    mOpenCvCameraView = (NativeCamResView) findViewById(R.id.test_view);
    mOpenCvCameraView.setCvCameraViewListener(this); 

}

@Override
public void onPause()
{
    super.onPause();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

@Override
public void onResume()
{
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_5, this, mLoaderCallback);


}

public void onDestroy() {
    super.onDestroy();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
}

public void onCameraViewStarted(int width, int height) {

    mGrayMat = new Mat(height, width, CvType.CV_8UC1 ...
(more)
edit flag offensive delete link more

Comments

@Moster dude, thats awesome, thank you for posting this :) so basically that NativeCameraView (and also your extension NativeCamResView) are a better variant of the CameraBridgeViewBase? your code looks exactly like what i have been searching for, i will try this tomorrow when i can access my code again :) i will let you know how i progress. once again, thank you very much, this is a great reply!

Max Muster gravatar imageMax Muster ( 2013-08-29 12:23:45 -0600 )edit
2

Basically there are 2 ways to access the camera. JavaCameraView and NativeCameraView. Both inherit from CameraBridgeViewBase and extend the features. The difference is that the JavaCameraView uses the standard android api to access the camera, NativeCameraView uses opencv's VideoCapture class which has the easy set and get functions to change camera features. Basically, you could also do that with the JavaCameraView, but Im not familiar with that :D So, I just showed you how to handle it with the NativeCameraView

Moster gravatar imageMoster ( 2013-08-29 12:45:37 -0600 )edit

@Moster thanks for explaining that, always good to learn new things :) i will reply to you when i tried your code tomorrow, im pretty sure this will work for my problem.

Max Muster gravatar imageMax Muster ( 2013-08-29 13:51:31 -0600 )edit

@Moster hello there. i just tried your code, i copied everything, fixed the package names and let the app run. i tried every focus mode you offer in your NativeCamResView, but the frames that get taken always look like this: http://i.imgur.com/BPsl3Gk.jpg they are still not focussed and sharp. is there anything i am doing wrong? thanks in advance :)

Max Muster gravatar imageMax Muster ( 2013-08-30 01:29:44 -0600 )edit
1

Could you test if the camera flash goes on with mOpenCvCameraView.setFlashMode(4);?

Moster gravatar imageMoster ( 2013-08-30 02:31:35 -0600 )edit

@Moster yes, the flash goes on with setFlashMode(4). that works fine. i also added Log messages in the switch/case block of your NativeCamResView class, to see if the correct focus mode gets selected. and indeed if i change the number in setFocusMode(int i) the Log displays the correct message. still there is no effect to my frames so far.

Max Muster gravatar imageMax Muster ( 2013-08-30 02:42:00 -0600 )edit
1

I have adjusted the code for the Activity. It contains some menu items that allow quick changing of the options. Try if maybe one of the focus modes works.

Moster gravatar imageMoster ( 2013-08-30 02:59:19 -0600 )edit

@Moster thanks for that, but it didn't change anything. i tried every focus mode, none makes any difference.

Max Muster gravatar imageMax Muster ( 2013-08-30 03:21:43 -0600 )edit
1

BTW, if this nice solution helps you fix it, please feel free to accept one of his answers.

StevenPuttemans gravatar imageStevenPuttemans ( 2013-08-30 04:34:01 -0600 )edit
1

@StevenPuttemans i will do that for sure :)

Max Muster gravatar imageMax Muster ( 2013-08-30 05:29:30 -0600 )edit

Question Tools

3 followers

Stats

Asked: 2013-08-29 07:14:17 -0600

Seen: 15,239 times

Last updated: Aug 30 '13