在Android中设置相机焦点区域

时间:2013-07-31 10:40:17

标签: android focus android-camera

在几个教程和示例之后,我想出了将相机焦点设置在特定位置的下一个算法,问题是相机完全忽略了点并执行了正常的整体焦点而不是我指定的矩形区域。我在算法中还缺少什么?这已经在Android 4.0及更高版本的几部手机上进行了测试,因此这些设备支持焦点区域API。请注意,我正在编写的应用程序仅在横向模式下工作。

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

3 个答案:

答案 0 :(得分:4)

在cameraParameters.setFocusAreas(focusAreas);之前,你应该添加这个:

cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

答案 1 :(得分:0)

这不是我的代码,但你可以尝试一下。所有信用都归到了Touch to select focus and metering area

这个例子的人

此外,我还为代码提供了一条小线,因为当我在Surface View上第二次点击时,应用程序正在破碎。所以请尽快使用下面的类(“AndroidCamera”):

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

    }
}

我所做的只是在camera.startFaceDetection();

之后添加drawingView.invalidate();

P.S。 在该网站上是下载整个项目的链接!

答案 2 :(得分:0)

对我来说,这项工作专注于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;

}

然后使用此方法处理触摸焦点区域

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

    }
}

我希望这个帮助