Set the camera focus area in Android

后端 未结 3 1188
心在旅途
心在旅途 2021-02-02 12:14

following several tutorials and examples I came up with the next algorithm to set the camera focus on a specific spot, the problem is that the camera completely ignores the spot

相关标签:
3条回答
  • 2021-02-02 12:48

    this is not my code, but you can try it. All credits go to the guy/s that made the example here Touch to select focus and metering area

    Also I contributed to there code with a small line because when I was clicking the second time on the Surface View the app was crushing. So plese be free to use the class ("AndroidCamera") bellow:

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

    All I did was to add camera.startFaceDetection(); after drawingView.invalidate();

    P.S. On that site is a link for downloading the entire project!

    0 讨论(0)
  • 2021-02-02 12:57

    before cameraParameters.setFocusAreas(focusAreas);, you should add this:

    cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    
    0 讨论(0)
  • 2021-02-02 13:01

    this work for me focus on camera 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;
    
    }
    

    then this method to handle touch focus area

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

    i hope this help

    0 讨论(0)
提交回复
热议问题