web-dev-qa-db-fra.com

Définir la zone de mise au point de la caméra dans Android

après plusieurs tutoriels et exemples, j'ai proposé l'algorithme suivant pour définir la mise au point de la caméra sur un point spécifique. Le problème est que la caméra ignore complètement le point et effectue une mise au point globale normale au lieu de la zone rect que j'ai spécifiée. Y a-t-il autre chose qui me manque dans l'algorithme? Ceci a été testé sur plusieurs téléphones, tous équipés d'Android 4.0 ou version ultérieure, de sorte que l'API de zone de focus est prise en charge sur ces appareils. Remarque, l'application que je suis en train d'écrire ne fonctionne qu'en mode paysage.

@Override
public boolean onTouchEvent(final MotionEvent event)
{
    if (event.getAction() == MotionEvent.ACTION_UP)
    {
        float x = event.getX();
        float y = event.getY();
        float touchMajor = event.getTouchMajor();
        float touchMinor = event.getTouchMinor();

        Rect touchRect = new Rect((int)(x - touchMajor / 2), (int)(y - touchMinor / 2), (int)(x + touchMajor / 2), (int)(y + touchMinor / 2));

        this.submitFocusAreaRect(touchRect);
    }
}

private void submitFocusAreaRect(final Rect touchRect)
{
    Camera.Parameters cameraParameters = camera.getParameters();

    if (cameraParameters.getMaxNumFocusAreas() == 0)
    {
        return;
    }

    // Convert from View's width and height to +/- 1000

    Rect focusArea = new Rect();

    focusArea.set(touchRect.left * 2000 / cameraSurfaceView.getWidth() - 1000, 
                      touchRect.top * 2000 / cameraSurfaceView.getHeight() - 1000,
                      touchRect.right * 2000 / cameraSurfaceView.getWidth() - 1000,
                      touchRect.bottom * 2000 / cameraSurfaceView.getHeight() - 1000);

    // Submit focus area to camera

    ArrayList<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
    focusAreas.add(new Camera.Area(focusArea, 1000));

    cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    cameraParameters.setFocusAreas(focusAreas);
    camera.setParameters(cameraParameters);

    // Start the autofocus operation

    camera.autoFocus(this);
}
19
PerracoLabs

ce travail pour moi se concentrer sur la caméra 1 Api

@Override
public boolean onTouchEvent(MotionEvent event) {

        //variable for storing the time of first click
        //constant for defining the time duration between the click that can be considered as double-tap
        final int MAX_DURATION = 200;
        // handle single touch events
        if (action == MotionEvent.ACTION_UP) {
            handleFocus(event, params);
            startTime = System.currentTimeMillis();
        }

        else if (event.getAction() == MotionEvent.ACTION_DOWN) {

            if(System.currentTimeMillis() - startTime <= MAX_DURATION)
            {

                //capture image on Double Tap
                mCamera.autoFocus(ShotActivity_CameraActivity.this);


            }
        }
    }
    return true;

}

alors cette méthode pour gérer la zone de mise au point tactile

public void handleFocus(MotionEvent event, Camera.Parameters params) {
    int pointerId = event.getPointerId(0);
    int pointerIndex = event.findPointerIndex(pointerId);
    // Get the pointer's current position
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);

    Rect touchRect = new Rect(
            (int) (x - 100),
            (int) (y - 100),
            (int) (x + 100),
            (int) (y + 100) );
    final Rect targetFocusRect = new Rect(
            touchRect.left * 2000/mTextureView.getWidth() - 1000,
            touchRect.top * 2000/mTextureView.getHeight() - 1000,
            touchRect.right * 2000/mTextureView.getWidth() - 1000,
            touchRect.bottom * 2000/mTextureView.getHeight() - 1000);

    List<String> supportedFocusModes = params.getSupportedFocusModes();
    if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
        try {
            List<Camera.Area> focusList = new ArrayList<Camera.Area>();
            Camera.Area focusArea = new Camera.Area(targetFocusRect, 1000);
            focusList.add(focusArea);


            params.setFocusAreas(focusList);
            params.setMeteringAreas(focusList);
            mCamera.setParameters(params);



           /* mCamera.autoFocus(this);*/
        } catch (Exception e) {
            e.printStackTrace();
            Log.i(TAG, "Unable to autofocus");
        }

    }
}

j'espère que cette aide 

0
Yudi karma

before cameraParameters.setFocusAreas (focusAreas) ;, vous devriez ajouter ceci:

cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
4
npace

ce n'est pas mon code, mais vous pouvez l'essayer. Tous les crédits vont aux gars qui ont fait l'exemple ici Touchez pour sélectionner la zone de mise au point et de mesure

J'ai aussi contribué au code avec une petite ligne parce que lorsque je cliquais une seconde fois sur la vue en surface, l'application était écrasante. Veuillez donc utiliser la classe ("AndroidCamera") ci-dessous:

import Java.io.FileNotFoundException;
import Java.io.IOException;
import Java.io.OutputStream;
import Java.util.ArrayList;
import Java.util.List;
import Java.util.concurrent.Executors;
import Java.util.concurrent.ScheduledExecutorService;
import Java.util.concurrent.TimeUnit;

import Android.app.Activity;
import Android.content.ContentValues;
import Android.content.Context;
import Android.content.pm.ActivityInfo;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.graphics.Paint;
import Android.graphics.PixelFormat;
import Android.graphics.Rect;
import Android.hardware.Camera;
import Android.hardware.Camera.AutoFocusCallback;
import Android.hardware.Camera.Face;
import Android.hardware.Camera.FaceDetectionListener;
import Android.hardware.Camera.Parameters;
import Android.hardware.Camera.PictureCallback;
import Android.hardware.Camera.ShutterCallback;
import Android.net.Uri;
import Android.os.Bundle;
import Android.provider.MediaStore.Images.Media;
import Android.view.LayoutInflater;
import Android.view.SurfaceHolder;
import Android.view.View;
import Android.view.ViewGroup.LayoutParams;
import Android.widget.Button;
import Android.widget.TextView;

public class AndroidCamera extends Activity implements SurfaceHolder.Callback{

    Camera camera;
    CameraSurfaceView cameraSurfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    LayoutInflater controlInflater = null;

    Button buttonTakePicture;
    TextView Prompt;

    DrawingView drawingView;
    Face[] detectedFaces;

    final int RESULT_SAVEIMAGE = 0;

    private ScheduledExecutorService myScheduledExecutorService;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        getWindow().setFormat(PixelFormat.UNKNOWN);
        cameraSurfaceView = (CameraSurfaceView)findViewById(R.id.camerapreview);
        surfaceHolder = cameraSurfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);

        drawingView = new DrawingView(this);
        LayoutParams layoutParamsDrawing
                = new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT);
        this.addContentView(drawingView, layoutParamsDrawing);

        controlInflater = LayoutInflater.from(getBaseContext());
        View viewControl = controlInflater.inflate(R.layout.control, null);
        LayoutParams layoutParamsControl
                = new LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT);
        this.addContentView(viewControl, layoutParamsControl);

        buttonTakePicture = (Button)findViewById(R.id.takepicture);
        buttonTakePicture.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                camera.takePicture(myShutterCallback,
                        myPictureCallback_RAW, myPictureCallback_JPG);
            }});

        /*
        LinearLayout layoutBackground = (LinearLayout)findViewById(R.id.background);
        layoutBackground.setOnClickListener(new LinearLayout.OnClickListener(){

   @Override
   public void onClick(View arg0) {
    // TODO Auto-generated method stub

    buttonTakePicture.setEnabled(false);
    camera.autoFocus(myAutoFocusCallback);
   }});
  */

        Prompt = (TextView)findViewById(R.id.Prompt);
    }

    public void touchFocus(final Rect tfocusRect){

        buttonTakePicture.setEnabled(false);
        camera.stopFaceDetection();

        //Convert from View's width and height to +/- 1000
        final Rect targetFocusRect = new Rect(
                tfocusRect.left * 2000/drawingView.getWidth() - 1000,
                tfocusRect.top * 2000/drawingView.getHeight() - 1000,
                tfocusRect.right * 2000/drawingView.getWidth() - 1000,
                tfocusRect.bottom * 2000/drawingView.getHeight() - 1000);

        final List<Camera.Area> focusList = new ArrayList<Camera.Area>();
        Camera.Area focusArea = new Camera.Area(targetFocusRect, 1000);
        focusList.add(focusArea);

        Parameters para = camera.getParameters();
        para.setFocusAreas(focusList);
        para.setMeteringAreas(focusList);
        camera.setParameters(para);

        camera.autoFocus(myAutoFocusCallback);

        drawingView.setHaveTouch(true, tfocusRect);
        drawingView.invalidate();
        camera.startFaceDetection();
    }

    FaceDetectionListener faceDetectionListener
            = new FaceDetectionListener(){

        @Override
        public void onFaceDetection(Face[] faces, Camera tcamera) {

            if (faces.length == 0){
                //Prompt.setText(" No Face Detected! ");
                drawingView.setHaveFace(false);
            }else{
                //Prompt.setText(String.valueOf(faces.length) + " Face Detected :) ");
                drawingView.setHaveFace(true);
                detectedFaces = faces;

                //Set the FocusAreas using the first detected face
                List<Camera.Area> focusList = new ArrayList<Camera.Area>();
                Camera.Area firstFace = new Camera.Area(faces[0].rect, 1000);
                focusList.add(firstFace);

                Parameters para = camera.getParameters();

                if(para.getMaxNumFocusAreas()>0){
                    para.setFocusAreas(focusList);
                }

                if(para.getMaxNumMeteringAreas()>0){
                    para.setMeteringAreas(focusList);
                }

                camera.setParameters(para);

                buttonTakePicture.setEnabled(false);

                //Stop further Face Detection
                camera.stopFaceDetection();

                buttonTakePicture.setEnabled(false);

    /*
     * Allways throw Java.lang.RuntimeException: autoFocus failed
     * if I call autoFocus(myAutoFocusCallback) here!
     *
     camera.autoFocus(myAutoFocusCallback);
    */

                //Delay call autoFocus(myAutoFocusCallback)
                myScheduledExecutorService = Executors.newScheduledThreadPool(1);
                myScheduledExecutorService.schedule(new Runnable(){
                    public void run() {
                        camera.autoFocus(myAutoFocusCallback);
                    }
                }, 500, TimeUnit.MILLISECONDS);

            }

            drawingView.invalidate();

        }};

    AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback(){

        @Override
        public void onAutoFocus(boolean arg0, Camera arg1) {
            // TODO Auto-generated method stub
            if (arg0){
                buttonTakePicture.setEnabled(true);
                camera.cancelAutoFocus();
            }

            float focusDistances[] = new float[3];
            arg1.getParameters().getFocusDistances(focusDistances);
            Prompt.setText("Optimal Focus Distance(meters): "
                    + focusDistances[Camera.Parameters.FOCUS_DISTANCE_OPTIMAL_INDEX]);

        }};

    ShutterCallback myShutterCallback = new ShutterCallback(){

        @Override
        public void onShutter() {
            // TODO Auto-generated method stub

        }};

    PictureCallback myPictureCallback_RAW = new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub

        }};

    PictureCallback myPictureCallback_JPG = new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub
   /*Bitmap bitmapPicture
    = BitmapFactory.decodeByteArray(arg0, 0, arg0.length); */

            Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());

            OutputStream imageFileOS;
            try {
                imageFileOS = getContentResolver().openOutputStream(uriTarget);
                imageFileOS.write(arg0);
                imageFileOS.flush();
                imageFileOS.close();

                Prompt.setText("Image saved: " + uriTarget.toString());

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            camera.startPreview();
            camera.startFaceDetection();
        }};

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // TODO Auto-generated method stub
        if(previewing){
            camera.stopFaceDetection();
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();

                Prompt.setText(String.valueOf(
                        "Max Face: " + camera.getParameters().getMaxNumDetectedFaces()));
                camera.startFaceDetection();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera = Camera.open();
        camera.setFaceDetectionListener(faceDetectionListener);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopFaceDetection();
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }

    private class DrawingView extends View{

        boolean haveFace;
        Paint drawingPaint;

        boolean haveTouch;
        Rect touchArea;

        public DrawingView(Context context) {
            super(context);
            haveFace = false;
            drawingPaint = new Paint();
            drawingPaint.setColor(Color.GREEN);
            drawingPaint.setStyle(Paint.Style.STROKE);
            drawingPaint.setStrokeWidth(2);

            haveTouch = false;
        }

        public void setHaveFace(boolean h){
            haveFace = h;
        }

        public void setHaveTouch(boolean t, Rect tArea){
            haveTouch = t;
            touchArea = tArea;
        }

        @Override
        protected void onDraw(Canvas canvas) {
            // TODO Auto-generated method stub
            if(haveFace){

                // Camera driver coordinates range from (-1000, -1000) to (1000, 1000).
                // UI coordinates range from (0, 0) to (width, height).

                int vWidth = getWidth();
                int vHeight = getHeight();

                for(int i=0; i<detectedFaces.length; i++){

                    if(i == 0){
                        drawingPaint.setColor(Color.GREEN);
                    }else{
                        drawingPaint.setColor(Color.RED);
                    }

                    int l = detectedFaces[i].rect.left;
                    int t = detectedFaces[i].rect.top;
                    int r = detectedFaces[i].rect.right;
                    int b = detectedFaces[i].rect.bottom;
                    int left = (l+1000) * vWidth/2000;
                    int top  = (t+1000) * vHeight/2000;
                    int right = (r+1000) * vWidth/2000;
                    int bottom = (b+1000) * vHeight/2000;
                    canvas.drawRect(
                            left, top, right, bottom,
                            drawingPaint);
                }
            }else{
                canvas.drawColor(Color.TRANSPARENT);
            }

            if(haveTouch){
                drawingPaint.setColor(Color.BLUE);
                canvas.drawRect(
                        touchArea.left, touchArea.top, touchArea.right, touchArea.bottom,
                        drawingPaint);
            }
        }

    }
}

Tout ce que j'ai fait était d'ajouter camera.startFaceDetection(); après drawingView.invalidate();

P.S. Sur ce site se trouve un lien pour télécharger le projet entier!