android相机对焦

1、利用硬件传感器去实现自动对焦


注册传感器:

[java]  view plain  copy
  1. SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);  
  2. sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);  

 

传感器接口:

[java]  view plain  copy
  1. implements SensorEventListener  

实现传感器接口方法:

[java]  view plain  copy
  1. public void onSensorChanged(SensorEvent event) {  
  2.        float x = event.values[0];  
  3.        float y = event.values[1];  
  4.        float z = event.values[2];  
  5.        if (initFirstSensor) {//初始化默认进入时候的坐标  
  6.            mLastX = x;  
  7.            mLastY = y;  
  8.            mLastZ = z;  
  9.            initFirstSensor = false;  
  10.            return;  
  11.        }  
  12.   
  13.        float deltaX = Math.abs(mLastX - x);  
  14.        float deltaY = Math.abs(mLastY - y);  
  15.        float deltaZ = Math.abs(mLastZ - z);  
  16.   
  17.        if (deltaX > 2.5 || deltaY > 2.5 || deltaZ > 2.5) {//计算坐标偏移值  
  18.            if (!isPhoto && mCamera != null) {  
  19.                playFocusAnimal(focusX, focusY);//播放对焦动画               
  20.                // mCamera.autoFocus(autoFocusCallback);//调用相机对焦  
  21.            }  
  22.        }   
  23.        mLastX = x;   
  24.        mLastY = y;   
  25.        mLastZ = z;   
  26.    }  


 

2、单点触摸对焦

监听touch事件拿到event:

[java]  view plain  copy
  1. public boolean onTouch(View v, MotionEvent event) {  
  2.                if (!isPhoto && mCamera != null) {  
  3.                    playFocusAnimal((int) event.getX(), (int) event.getY());  
  4.                    touchFocus(event);  
  5.                }  
  6.                return false;  
  7.            }  

根据触摸位置设置对焦点的对焦权值:

(解释一下:每个对焦区域是一个具有特定权值的长方形。方向与重力感应的方向有关。而且不会受到 setDisplayOrientation(int)旋转画面设置的影响。矩形的坐标范围指定从-1000到1000 ,(-1000,-1000)是左上角点(1000,1000)是右下角点。对焦权值的取值范围是1-1000,权值为矩形范围像素所平分,这意味着同样的权值对焦区域大的对整体的对焦影响小。

理论结合实际的说就是,假如你的整个屏幕的宽度是width,那么点击某个位置算x,那么要划定对焦区域,就要告诉相机对焦的坐标,根据对焦坐标的范围为-1000到1000,所以要用公式计算对应的对焦坐标实际上是: x/width*2000-1000=对焦x坐标,同样获取到对焦y坐标,然后以x,y为中心,指定对焦区域,设置对焦权值,越大表示优先对焦该位置)

代码:

[java]  view plain  copy
  1. private void touchFocus(MotionEvent event) {  
  2.        mCamera.cancelAutoFocus();  
  3.        Camera.Parameters p = mCamera.getParameters();  
  4.        float touchX = (event.getRawX() / screenWidth) * 2000 - 1000;  
  5.        float touchY = (event.getRawY() / screenHeight) * 2000 - 1000;  
  6.        int left = clamp((int) touchX - AREA_SIZE / 2, -10001000);  
  7.        int right = clamp(left + AREA_SIZE, -10001000);  
  8.        int top = clamp((int) touchY - AREA_SIZE / 2, -10001000);  
  9.        int bottom = clamp(top + AREA_SIZE, -10001000);  
  10.        Rect rect = new Rect(left, top, right, bottom);  
  11.        if (p.getMaxNumFocusAreas() > 0) {  
  12.            List<Camera.Area> areaList = new ArrayList<Camera.Area>();  
  13.            areaList.add(new Camera.Area(rect, 1000));  
  14.            p.setFocusAreas(areaList);  
  15.        }  
  16.        if (p.getMaxNumMeteringAreas() > 0) {  
  17.            List<Camera.Area> areaList = new ArrayList<Camera.Area>();  
  18.            areaList.add(new Camera.Area(rect, 1000));  
  19.            p.setMeteringAreas(areaList);  
  20.        }  
  21.        p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);  
  22.        try {  
  23.            mCamera.setParameters(p);  
  24.        } catch (Exception e) {  
  25.   
  26.        }  
  27.        mCamera.autoFocus(autoFocusCallback);  
  28.    }  
  29.   
  30. private int clamp(int x, int min, int max) {//保证坐标必须在min到max之内,否则异常  
  31.        if (x > max) {  
  32.            return max;  
  33.        }  
  34.        if (x < min) {  
  35.            return min;  
  36.        }  
  37.        return x;  
  38.    }  


 

3、小米的坑

miui上的时候如果设置预览分辨率过高,则会导致拍照时候小米假死,无响应

解决方案:预览分辨率设置在屏幕分辨率左右,对miui特殊对待

[java]  view plain  copy
  1. private void initCameraParameters() {  
  2.        Camera.Parameters parameters = mCamera.getParameters();  
  3.        List<Camera.Size> vSizeList = parameters.getSupportedPictureSizes();  
  4.        Camera.Size showSize = null;  
  5.        Camera.Size tempSize;  
  6.        Camera.Size miuiSize = null;  
  7.        for (int num = 0; num < vSizeList.size(); num++) {  
  8.            tempSize = vSizeList.get(num);  
  9.            try {  
  10.                parameters.setPreviewSize(tempSize.width, tempSize.height);  
  11.                mCamera.setParameters(parameters);  
  12.                if (showSize == null || (showSize != null && tempSize.width > showSize.width)) {  
  13.                    showSize = tempSize;//设置最高可以支持的屏幕分辨率  
  14.                }  
  15.                if (screenWidth < tempSize.width && (miuiSize == null || miuiSize.width > tempSize.width)) {  
  16.                    miuiSize = tempSize;//设置miui的预览大小在屏幕分辨率左右  
  17.                }  
  18.            } catch (Exception e) {  
  19.   
  20.            }  
  21.            try {  
  22.                parameters.setPictureSize(tempSize.width, tempSize.height);  
  23.                mCamera.setParameters(parameters);  
  24.                if (highSize == null || (highSize != null && tempSize.width > highSize.width)) {  
  25.                    highSize = tempSize;//设置相机可支持的最高保存分辨率  
  26.                }  
  27.            } catch (Exception e) {  
  28.   
  29.            }  
  30.            if (screenWidth > tempSize.width && (nomalSize == null || nomalSize.width < tempSize.width)) {  
  31.                nomalSize = tempSize;//设置一般相机保存的分辨率  
  32.            }  
  33.        }  
  34.        if (showSize != null) {  
  35.            if (android.os.Build.MANUFACTURER.equals("Xiaomi")) {//对待小米特殊设置  
  36.                parameters.setPreviewSize(miuiSize.width, miuiSize.height);  
  37.            } else {  
  38.                parameters.setPreviewSize(showSize.width, showSize.height);  
  39.            }  
  40.        }  
  41.        if (nomalSize != null) {  
  42.            parameters.setPictureSize(nomalSize.width, nomalSize.height);  
  43.            isNomal = true;  
  44.            if (picQualityButton != null) {  
  45.                picQualityButton.setImageDrawable(getResources().getDrawable(R.drawable.camera_pic_quality_nomal));  
  46.            }  
  47.        }  
  48.        if (isSupportFlash) {  
  49.            switch (currentFlashMode % 3) {  
  50.                case 0:  
  51.                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);  
  52.                    break;  
  53.                case 1:  
  54.                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);  
  55.                    break;  
  56.                case 2:  
  57.                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);  
  58.                    break;  
  59.            }  
  60.        }   
  61.        parameters.setPictureFormat(PixelFormat.JPEG);  
  62.        parameters.setJpegQuality(100);  
  63.        mCamera.setParameters(parameters);  
  64.        mCamera.startPreview();  
  65.        playFocusAnimal(screenWidth / 2, screenHeight / 2);  
  66.        mCamera.autoFocus(autoFocusCallback);  
  67.    }  

author:iamwsbear@gmail.com

http://blog.csdn.net/iamws/article/details/50401886

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值