40

私は数日間この機能と戦ってきました...

そのカメラは、私が定義したフォーカス エリアを無視 (?) しているようです。コードのスニペットは次のとおりです。

フォーカシング:

protected void focusOnTouch(MotionEvent event) {
    if (camera != null) {
        Rect rect = calculateFocusArea(event.getX(), event.getY());

        Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
        parameters.setFocusAreas(Lists.newArrayList(new Camera.Area(rect, 500)));

        camera.setParameters(parameters);
        camera.autoFocus(this);
    }
}

フォーカス エリアの計算:

private Rect calculateFocusArea(float x, float y) {
    int left = clamp(Float.valueOf((x / getSurfaceView().getWidth()) * 2000 - 1000).intValue(), focusAreaSize);
    int top = clamp(Float.valueOf((y / getSurfaceView().getHeight()) * 2000 - 1000).intValue(), focusAreaSize);

    return new Rect(left, top, left + focusAreaSize, top + focusAreaSize);
}

からのいくつかのログイベントCamera.AutoFocusCallback#onAutoFocus

Log.d(TAG, String.format("Auto focus success=%s. Focus mode: '%s'. Focused on: %s", focused, camera.getParameters().getFocusMode(), camera.getParameters().getFocusAreas().get(0).rect.toString()));

08-27 11:19:42.240: DEBUG/MyCameraActivity(26268): Auto focus success=true. Focus mode: 'auto'. Focused on: Rect(-109, 643 - -13, 739)
08-27 11:19:55.514: DEBUG/MyCameraActivity(26268): Auto focus success=true. Focus mode: 'auto'. Focused on: Rect(20, 457 - 116, 553)
08-27 11:19:58.037: DEBUG/MyCameraActivity(26268): Auto focus success=true. Focus mode: 'auto'. Focused on: Rect(-159, 536 - -63, 632)
08-27 11:20:00.129: DEBUG/MyCameraActivity(26268): Auto focus success=true. Focus mode: 'auto'. Focused on: Rect(-28, 577 - 68, 673)

視覚的には、ログに記録された領域にフォーカスが成功しているように見えますが、突然フォーカスが失われ、中央にフォーカスされる(0, 0)か、より大きな部分SurfaceViewが取得されます。

focusAreaSize計算に使用するのは約210px(96dp)です。Camera.getParameters().getMaxNumFocusAreas()であるHTC One でのテスト1

初期フォーカスモード(最初のタップ前)は に設定されていFOCUS_MODE_CONTINUOUS_PICTUREます。

ここで何か間違ったことをしていますか?長方形のサイズや重みをいじってCamera.Areaも、目立った効果は見られません。

4

5 に答える 5

54

私の問題ははるかに単純でした:)

私がしなければならなかったのは、以前はオートフォーカスと呼ばれていたものをキャンセルすることだけです。基本的に、アクションの正しい順序は次のとおりです。

protected void focusOnTouch(MotionEvent event) {
    if (camera != null) {

        camera.cancelAutoFocus();
        Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);
        Rect meteringRect = calculateTapArea(event.getX(), event.getY(), 1.5f);

        Parameters parameters = camera.getParameters();
        parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
        parameters.setFocusAreas(Lists.newArrayList(new Camera.Area(focusRect, 1000)));

        if (meteringAreaSupported) {
            parameters.setMeteringAreas(Lists.newArrayList(new Camera.Area(meteringRect, 1000)));
        }

        camera.setParameters(parameters);
        camera.autoFocus(this);
    }
}

アップデート

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    ...
    Parameters p = camera.getParameters();
    if (p.getMaxNumMeteringAreas() > 0) {
       this.meteringAreaSupported = true;
    }
    ...
}

/**
 * Convert touch position x:y to {@link Camera.Area} position -1000:-1000 to 1000:1000.
 */
private Rect calculateTapArea(float x, float y, float coefficient) {
    int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();

    int left = clamp((int) x - areaSize / 2, 0, getSurfaceView().getWidth() - areaSize);
    int top = clamp((int) y - areaSize / 2, 0, getSurfaceView().getHeight() - areaSize);

    RectF rectF = new RectF(left, top, left + areaSize, top + areaSize);
    matrix.mapRect(rectF);

    return new Rect(Math.round(rectF.left), Math.round(rectF.top), Math.round(rectF.right), Math.round(rectF.bottom));
}

private int clamp(int x, int min, int max) {
    if (x > max) {
        return max;
    }
    if (x < min) {
        return min;
    }
    return x;
}
于 2013-10-09T12:34:11.107 に答える
5

設定のほかに:

parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

設定する必要があります:

parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

本当の「ライブ」オートフォーカスが必要な場合。また、利用可能なフォーカスを確認することもお勧めします:

List<String> focusModes = parameters.getSupportedFocusModes();
LLog.d("focusModes=" + focusModes);
if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
    parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

Samsung S6 では、カメラのプレビューを取得した後、少し遅れて (~ 500 ミリ秒) これを設定する必要があります。

于 2016-03-27T14:24:58.483 に答える
3

私は今日この問題を抱えていました:/

そして、何時間も格闘した後、解決策を見つけました!

奇妙ですが、フォーカスエリアを設定する直前にフォーカスモードを「マクロ」に設定すると問題が解決したようです;)

params.setFocusMode(Camera.Parameters.FOCUS_MODE_MACRO);
params.setFocusAreas(focusAreas);
mCamera.setParameters(params);

Android 4.1.2を搭載したGalaxy S3を持っています

これがあなたにとってもうまくいくことを願っています:)

于 2013-09-29T00:28:53.870 に答える
2

FOCUS_MODE_FIXED を使用する

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        mCamera = Camera.open(mCameraId);
    } else {
        mCamera = Camera.open();
    }
cameraParams = mCamera.getParameters();
// set the focus mode
cameraParams.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
// set Camera parameters
mCamera.setParameters(cameraParams);
于 2017-01-12T15:26:11.503 に答える