Android相机按需自动对焦

29

内置的摄像机应用程序(例如HTC EVO上的应用程序)似乎仅在预览图像发生更改时调用 camera.autoFocus()。 如果您保持相机稳定,则不会发生 camera.autoFocus()
我想在 camera.startPreview()处于活动状态时复制此行为,如下面的初始预览设置代码:

camera = camera.open();
Camera.Parameters parameters = camera.getParameters();
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
{
    parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();

我找到的所有关于autoFocus()的示例似乎都是每500毫秒到2000毫秒调用一次,或者在拍照或录像开始前的瞬间调用一次。
EVO Camcorder应用程序似乎使用传感器或算法触发autoFocus()。无论如何触发autoFocus(),它都表现出色。是否有人知道如何在需要时按需触发autoFocus(),例如当相机靠近或远离主题时,或者稍微移动时?

5个回答

23

Android自API Level 9(Gingerbread)引入了连续自动对焦。它比定期调用Camera.autoFocus效果更好。


2
一些HTC设备即使使用API>9也不支持连续自动对焦。使用parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)来检查它是否被支持。 - d2vid
@d2vid,没错。我正在开发一个API 15的HTC应用,它不支持连续自动对焦! - Johnny
从2018起的编写经验表明,在大多数设备上,特别是在近距离物体上,Android 自动对焦并不比定期轮询自动对焦更有效。 - cyberj0g

19

我在一个应用程序中遇到了同样的问题。

我的解决方案是使用传感器监听器,在用户将设备摇动到某个阈值时自动对焦。这是代码。

public void setCameraFocus(AutoFocusCallback autoFocus){
if (mCamera.getParameters().getFocusMode().equals(mCamera.getParameters().FOCUS_MODE_AUTO) ||
        mCamera.getParameters().getFocusMode().equals(mCamera.getParameters().FOCUS_MODE_MACRO)){
    mCamera.autoFocus(autoFocus);
}

自动对焦的回调函数:

// this is the autofocus call back
private AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){

    public void onAutoFocus(boolean autoFocusSuccess, Camera arg1) {
        //Wait.oneSec();
        mAutoFocus = true;
    }};

调用焦点的方法。

public void onSensorChanged(SensorEvent event) {

if (mInvalidate == true){
    mView.invalidate();
    mInvalidate = false;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
if (!mInitialized){
    mLastX = x;
    mLastY = y;
    mLastZ = z;
    mInitialized = true;
}
float deltaX  = Math.abs(mLastX - x);
float deltaY = Math.abs(mLastY - y);
float deltaZ = Math.abs(mLastZ - z);

if (deltaX > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}
if (deltaY > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing)
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}
if (deltaZ > .5 && mAutoFocus){ //AUTOFOCUS (while it is not autofocusing) */
    mAutoFocus = false;
    mPreview.setCameraFocus(myAutoFocusCallback);
}

mLastX = x;
mLastY = y;
mLastZ = z;

}

你可以在这里查看完整的项目:http://adblogcat.com/a-camera-preview-with-a-bounding-box-like-google-goggles/


2
如果(mAutoFocus &&(deltaX > .5 || deltaY > .5 || deltaZ > .5))则也可以很好地完成。 - Nacho Coloma
你好,我正在使用表面纹理而不是表面持有者,并且想知道如何将自动对焦回调传递给函数?Reader类调用相机API Camera c1 = Camara(width, height, context,texture); // Camera类具有相机功能的实现 c1.setCameraFocus(); // 我可以在这里添加它,但是如何传递回调,因为它在相机类中已经被提到了。 - Vishwesh Soni

2
为拍照,您可以设置此选项
在此模式下,应用程序可以调用autoFocus(AutoFocusCallback)。如果自动对焦正在扫描中,则对焦回调将在其完成时返回。如果自动对焦未在扫描中,则对焦回调将立即返回一个布尔值,指示对焦是否清晰。然后,应用程序可以决定是立即拍照还是将对焦模式更改为自动,并运行完整的自动对焦循环。

2

如果您的相机视野中有一个白色盒子闪光灯(从代码而不是真实的盒子),则可以使用更简单的技术调用重新聚焦,这是非常可能的。 我拥有EVO 4G,之前的一位帖子作者是正确的,自从更新到姜饼版本以来,它会持续重新聚焦,而无需更改其所看的内容。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接