【Android Camera1】Camera1 对焦(一) UI坐标系和相机坐标系

一、简介

本篇文章为对焦系列文章的第一篇:主要讲解UI坐标系和相机坐标系。后续其他相关文章如下:

相关文章:

  1. Camera1 对焦(二) 对焦区域计算的几种方式(Touch to Focus)
  2. Camera1 对焦(三) 对焦功能标准化流程
  3. Camera1 Parameters参数详解(二)—— 3A算法 (对焦、曝光、白平衡)
  4. Android AF Work Flow安卓自动对焦工作流程
  5. Camera.Area相关知识 -> 【Android Camera1】Camera1源码分析【2.1】Camera.Area
  6. AF对焦模式相关知识 -> 【Android Camera1】Camera1 Parameters参数详解(二)—— 3A算法 (对焦、曝光、白平衡) 【2】AF对焦

二、对焦和区域测光

日常使用照片拍照有如下几种场景:

  1. 默认自动对焦【视频、拍照连续对焦】
  2. 点击某一个区域单次对焦

从 Android 4.0(API 级别 14)开始,在拍摄图片或视频时,能够在图片中指定区域,并将这些值传递给相机硬件用于控制固定区域进行对焦和测光。区域对焦和区域测光可通过Parameters对应的Key进行设置。

2.1 区域相关设置代码

/**
 * <p>Gets the current focus areas. Camera driver uses the areas to decide
 * focus.</p>
 *
 * <p>Before using this API or {@link #setFocusAreas(List)}, apps should
 * call {@link #getMaxNumFocusAreas()} to know the maximum number of
 * focus areas first. If the value is 0, focus area is not supported.</p>
 *
 * <p>Each focus area is a rectangle with specified weight. The direction
 * is relative to the sensor orientation, that is, what the sensor sees.
 * The direction is not affected by the rotation or mirroring of
 * {@link #setDisplayOrientation(int)}. Coordinates of the rectangle
 * range from -1000 to 1000. (-1000, -1000) is the upper left point.
 * (1000, 1000) is the lower right point. The width and height of focus
 * areas cannot be 0 or negative.</p>
 *
 * <p>The weight must range from 1 to 1000. The weight should be
 * interpreted as a per-pixel weight - all pixels in the area have the
 * specified weight. This means a small area with the same weight as a
 * larger area will have less influence on the focusing than the larger
 * area. Focus areas can partially overlap and the driver will add the
 * weights in the overlap region.</p>
 *
 * <p>A special case of a {@code null} focus area list means the driver is
 * free to select focus targets as it wants. For example, the driver may
 * use more signals to select focus areas and change them
 * dynamically. Apps can set the focus area list to {@code null} if they
 * want the driver to completely control focusing.</p>
 *
 * <p>Focus areas are relative to the current field of view
 * ({@link #getZoom()}). No matter what the zoom level is, (-1000,-1000)
 * represents the top of the currently visible camera frame. The focus
 * area cannot be set to be outside the current field of view, even
 * when using zoom.</p>
 *
 * <p>Focus area only has effect if the current focus mode is
 * {@link #FOCUS_MODE_AUTO}, {@link #FOCUS_MODE_MACRO},
 * {@link #FOCUS_MODE_CONTINUOUS_VIDEO}, or
 * {@link #FOCUS_MODE_CONTINUOUS_PICTURE}.</p>
 *
 * @return a list of current focus areas
 */
public List<Area> getFocusAreas() {
    return splitArea(get(KEY_FOCUS_AREAS));
}

public void setFocusAreas(List<Area> focusAreas) {
    set(KEY_FOCUS_AREAS, focusAreas);
}


/**
 * Gets the maximum number of focus areas supported. This is the maximum
 * length of the list in {@link #setFocusAreas(List)} and
 * {@link #getFocusAreas()}.
 *
 * @return the maximum number of focus areas supported by the camera.
 * @see #getFocusAreas()
 */
public int getMaxNumFocusAreas() {
    return getInt(KEY_MAX_NUM_FOCUS_AREAS, 0);
}

分析:

  1. getMaxNumFocusAreas()获取当前Camera Lens支持对焦区域的个数。如果为0则表示不支持对焦固定的输入区域
  2. 通过设置focus-area来控制Camera Lens针对特定的区域进行对焦
  3. focus-area是一个rect。范围为【-1000,1000】,weight:【1,1000】,可参看Camera1源码分析【Java层】【2.1】
  4. setFocusAreas(null) -> 交给Camera自己控制
  5. 和zoom值没关系。区域对应的始终是zoom=1.0x的画面。详细可参看后续Camera1对焦之zoom

2.2 代码举例

官网示例代码如下:

// Create an instance of Camera
// Create an instance of Camera
camera = getCameraInstance();

// set Camera parameters
Camera.Parameters params = camera.getParameters();

if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported
    List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();

    Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
    meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
    Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
    meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
    params.setMeteringAreas(meteringAreas);
}

if (params.getMaxNumFocusAreas() > 0){ // check that focus areas are supported
    List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();

    Rect areaRect1 = new Rect(-100, -100, 100, 100);    // specify an area in center of image
    focusAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%
    Rect areaRect2 = new Rect(800, -1000, 1000, -800);  // specify an area in upper right of image
    focusAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%
    params.setFocusAreas(focusAreas);
}

camera.setParameters(params);

分析

  1. 首先通过getMaxNumFocusAreas()和getMaxNumMeteringAreas()来判断是否支持区域对焦和区域测光。
  2. 设置了2个不同权重的Rect进行区域对焦和区域测光。

三、不同坐标系

3.1 相机坐标系

图一
图一

图一中,给出了相机的坐标系,注意这里是横屏的。相机的坐标系中值的范围是[-1000,1000]。因此在左上角是[-1000, 1000]。右下角是[1000,1000]。

图一中也给出了要设置的rect(333,333,667,667)。如果调用代码1则会在该区域对焦。如果调用代码2,则会在该区域测光AE

代码1:
************
params.setFocusAreas(new Camera.Area(rect))

代码2:
************
params.setMeteringAreas(new Camera.Area(rect))

3.2 UI坐标系

3.1我们阐述了相机坐标系,但是图是横的,实际使用手机,大部分的场景是竖直的。因此我们参看图二。

图二
在这里插入图片描述

图二有左右2个图,不同的orientation。这里一定要明白:

相机的输出流会和后置Camera Lens有90的的夹角;和前置Camera Lens有270度的夹角

因此在右侧整的的UI坐标系中,左上角是(0,0),右下角是(mPreviewWidth, mPreviewHeight),orientation:90度。

那么对应到相机的坐标系中,

  • 3.1 横屏:左上角是(-1000, -1000),右下角是(1000,1000)。
  • 竖直:右上角是(-1000, -1000),左下角是(1000,1000)。

所以当点击某个区域对焦时,需要做的工作就是:把UI坐标系的点坐标转换成为相机坐标系下的点坐标对应的rect区域

四、总结

这里总结一下【手机竖直】

  • UI坐标系:左上角是(0,0),右下角是(mPreviewWidth, mPreviewHeight)
  • 相机坐标系:右上角是(-1000, -1000),左下角是(1000,1000)
  • 点击对焦测光:Point(x, y)[ui] -> Point(x, y)[camera] -> Rect(l, t, r, b)[camera]

具体的点击对焦测光计算算法如下:

  1. 获取点击对应的Point(x, y)
  2. Point(x, y)根据相机的orient方向,来判断是否进行x, y互换【后置从UI到相机参考系需要逆时针旋转-90度】
  3. Point(x, y) 从(0, 0, mPreviewWidth, mPreviewHeight) => (-1000, -1000, 1000, 1000)
  4. Point(x, y) [camera] 根据AspectRatio和区域Size => Rect[Camera]

下一篇将讲解Camera1对焦区域具体的计算算法和相关代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值