Quelle est la bonne façon de mettre en œuvre Tap to Focus pour caméra?

je travaille sur une application qui a un écran de caméra personnalisé, pour lequel je suis censé mettre en œuvre tap to focus, comme dans L'application de caméra Android(plus spécifiquement, le Galaxy S4).

j'ai essayé d'utiliser les étapes soulignées ici , mais il ne semble pas causer de mise au point notable. Le mode Focus est réglé sur image continue (nous ne supportons qu'un périphérique spécifique).

quand l'utilisateur tape sur l'aperçu de la caméra, j'ai besoin pour être en se concentrant sur la moitié supérieure de l'image. Pour cela, j'utilise le 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);
}

Je ne veux pas de mise au point automatique car il faut trop de temps pour se concentrer sur l'image. Je suis intéressé uniquement dans la moitié supérieure de l'image. Quelqu'un a-t-il implémenté avec succès Tap to Focus avec le mode Image continue?

22
demandé sur Vinay S Shenoy 2013-08-01 16:13:27

4 réponses

est entré dans ce numéro récemment. Comme L'a dit MatheusJardimB, cette question aide beaucoup.

cependant, dans mon cas, je voulais commencer dans le mode ContinuousPicture puis être en mesure de taper pour mettre au point puis continuer avec le mode ContinuousPicture .

j'ai réussi à le faire fonctionner en utilisant la méthode onAutoFocus du Camera.AutoFocusCallback() . Je ne suis pas sûr si c'est la meilleure ou la plus jolie façon de le faire, mais il semble fonctionner.

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

vous pouvez simplement changer le domaine d'intérêt en

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

et ça devrait marcher.

mise à JOUR

j'ai récemment acquis un Samsung S5 et je l'ai testé. Ça n'a pas très bien marché, donc j'ai ajouté quelques modifications et ça marche maintenant. Cela a également été testé avec succès sur Galaxy S6 et Galaxy Note4.

voici le code modifié:

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;
    }
});
25
répondu Dude 2018-09-18 10:03:42

ce a la solution. J'ai juste ajouté l'implémentation de certaines méthodes manquantes dans son 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;
}

/ / implémenter ce callback pour déclencher la mise au point.

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!");
            }
        }
    };
15
répondu ahmed_khan_89 2017-05-23 10:31:09

l'Un de l'autre répond les causes de votre appareil photo à jeter les points précédemment donnée, et revenir à une attention continue qui je ne pense pas de sens.

aussi si vous jetez un oeil au lien dans le post la réponse originale utilise des paramètres.setFocusMode (paramètres.Focus _MODE_AUTO);

j'ai mis en œuvre ce qui précède avec cette ligne de code au lieu de la mise au point continue et il semble fonctionner beaucoup mieux.

2
répondu Arjun 2017-05-23 10:31:09

j'ai le même problème. J'ai vérifié sur de nombreux appareils, et de nombreuses versions Android.

Il semble que zone de mise au point ne fonctionne pas en CONTINU focus en mode .

ma solution est de définir le mode de mise au point automatique ou MACRO avec le réglage de la zone de mise au point:

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

veuillez noter que L'application stock Camera sur Galaxy S3 & S4 fonctionne de la même manière: elle est en permanence en mode continu. Lorsque vous toucher l'écran il passe à auto & met zone de mise au point. Mais après un certain temps, il revient en mode continu, et la zone de mise au point retourne au centre de l'écran.

j'espère que ça vous aidera.

-1
répondu Grzegorz D. 2013-12-08 15:03:16