web-dev-qa-db-fra.com

Ensemble AndroidFocusArea et Auto Focus

Je me bats avec cette fonctionnalité depuis quelques jours maintenant ...

Il semble que la caméra ignore (?) Les zones de mise au point que j'ai définies. Voici des extraits du code:

Mise au point:

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);
    }
}

Calcul de la zone de mise au point: 

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);
}

Quelques événements de journal de 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)

Visuellement, il semble que la focalisation réussisse sur la zone enregistrée, mais elle perd soudainement la focalisation sur le (0, 0) central, ou ce qui prend une plus grande part de SurfaceView est obtenu.

focusAreaSize utilisé dans le calcul est d'environ 210px (96dp) . Test sur HTC One où Camera.getParameters().getMaxNumFocusAreas() est 1.

Le mode de mise au point initiale (avant le premier toucher) est réglé sur FOCUS_MODE_CONTINUOUS_PICTURE.

Est-ce que je fais quelque chose de mal ici? Tinkering with Camera.Area La taille ou le poids du rectangle ne montre aucun effet notable.

35
Martynas Jurkus

Mon problème était beaucoup plus simple :)

Tout ce que je devais faire, c’est d’annuler ce que nous appelions auparavant l’autofocus. Fondamentalement, le bon ordre d'actions est le suivant:

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);
    }
}

Mettre à jour

@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;
}
50
Martynas Jurkus

A côté du réglage:

parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

vous devez définir:

parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);

si vous voulez une vraie mise au point "en direct". Aussi, il sera bon de vérifier les focus disponibles:

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

Sur le Samsung S6, vous devez régler ce paramètre peu de temps après (~ 500 ms) après avoir obtenu un aperçu de l'appareil photo.

4
ivan.panasiuk

J'ai eu ce problème aujourd'hui: /

Et après des heures de lutte, j'ai trouvé la solution!

C'est étrange, mais il semble que le fait de définir le mode de mise au point sur "macro" juste avant de définir les zones de mise au point a résolu le problème;)

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

J'ai Galaxy S3 avec Android 4.1.2

J'espère que cela fonctionnera pour vous non plus :)

2
Grzegorz D.

utilisez 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);
0
zohre