繁体   English   中英

Android相机应用:点测光

[英]Android Camera App: Spot Metering

我正在尝试使用Android手机实现Spot Metering。 parameters.set(“自动曝光”,“点测光”);

但是,我对计量的工作方式感到有些困惑。 如果我理解正确,Spot Metering通过选择用于设置曝光值的区域来工作。

但是,当展平Camera.Parameters类并显示结果时,计量区域为(0,0,0,0,0)[意味着它具有零宽度,高度和重量],而自动曝光设置正确“点-metering”。 但是,在API中,“getMeteringAreas()”文档说计量区域的宽度和高度不能为零。

那么,当测光面积为0时,如何使用“点测光”? 我尝试将测光区域设置在右上角,但它对曝光没有任何影响。

这让我相信自动曝光=点测光与测光区域没有任何关系....这很奇怪。

如果情况并非如此,有人可以帮助我理解我做错了什么吗? 如果您需要更多信息,我将很乐意提供代码。

如果是这种情况(如计量区域与点测光无关),有人可以帮我弄清楚如何选择自动曝光测光仪的位置吗? 我认为它默认为中心。

谢谢!

MeteringAreas参数用于自动对焦测光。

曝光测光模式没有Android api。 您需要找到适当的未记录的参数名称和值来设置它(例如,通过native_getParameters转储所有参数)。

例如,对于Samsung Galaxy Note 3参数名称是metering和接受的值是centermatrixspot 所以你只需要调用set("metering", "spot"); 它神奇地起作用。

计量是一种依赖于设备的问题。

在API级别14之前,没有用于管理计量的标准API,我认为有些品牌选择自己的方式来管理它(在您的情况下:“自动曝光”关键字),但不是通过标准API。 这就是您无法获得有效区域的原因。 parameters.flatten()中的计量区域(0,0,0,0,0)表示不支持计量区域(权重= 0),我猜getMaxNumMeteringAreas()返回0:

应该首先调用getMaxNumMeteringAreas()来了解最大计量区域数。 如果值为0,则不支持计量区域。

到目前为止,很少有设备支持计量区域(根据我的经验3/20)。

这个答案适用于Camera API 1

首先检查设备是否支持设置测量区域,使用:

Camera.Parameters params = mCamera.getParameters();
if (params.getMaxNumMeteringAreas() > 0) {
    // Supported!
} else {
    // Not supported
}

然后,如果支持,则使用您的ROI(感兴趣的区域)创建一个Rect对象。
您需要考虑相机的旋转,因为在不同的设备上,相机的方向可能不同。 找出相机旋转超出了这个答案的范围,抱歉:)

private Rect getRotatedRect(Rect rect, int previewWidth, int previewHeight, int cameraRotation) {

    int resultLeft = rect.left;
    int resultTop = rect.top;
    int resultRight = rect.right;
    int resultBottom = rect.bottom;

    switch (cameraRotation) {
        case 90:
            resultLeft = top;
            resultTop = previewHeight - right;
            resultRight = bottom;
            resultBottom = previewHeight - left;
            break;
        case 180:
            resultLeft = previewWidth - right;
            resultTop = previewHeight - bottom;
            resultRight = previewWidth - left;
            resultBottom = previewHeight - top;
            break;
        case 270:
            resultLeft = previewWidth - bottom;
            resultTop = left;
            resultRight = previewWidth - top;
            resultBottom = right;
            break;
    }

    return new Rect(resultLeft, resultTop, resultRight, resultBottom);
}

请注意,不要使用X和Y坐标的绝对值,
相机API使用从(-1000,-1000)到(1000,1000)的坐标。

所以你必须缩放你的Rect,以便(-1000,-1000)代表左上角
和(1000,1000)代表相机的右下角。

示例:如果您的相机预览尺寸为800x480且您的ROI为Rect(200,120,600,360),
你应该创建一个新的Rect(-500,-500,500,500)。

private Rect getScaledRect(Rect rect, int previewWidth, int previewHeight) {
    float widthUnit = previewWidth / 2000f;
    float heightUnit = previewHeight / 2000f;

    int adjustedLeft = Math.max((int) (rect.left / widthUnit - 1000), -1000);
    int adjustedTop = Math.max((int) (rect.top / heightUnit - 1000), -1000);
    int adjustedRight = Math.max((int) (rect.right / widthUnit - 1000), -1000);
    int adjustedBottom = Math.max((int) (rect.bottom / heightUnit - 1000), -1000);

    return new Rect(adjustedLeft, adjustedTop, adjustedRight, adjustedBottom);
}

然后最后将新的Rect设置为计量区域。
您可以设置计量区域的权重(int从0到1000),它决定了您定义的区域对最终曝光计算的影响程度。

总而言之:

Camera.Parameters params = mCamera.getParameters();
if (params.getMaxNumMeteringAreas() > 0) {
    // Supported!

    // Create rotated Rect
    Rect rotatedRect = getRotatedRect(yourAbsoluteCoordinatesROIRect, mPreviewSize.width, mPreviewSize.height, mCameraOrientation);

    // Scale Rect to make it appropriate for Camera API
    Rect scaledRect = getScaledRect(rotatedRect, mPreviewSize.width, mPreviewSize.height);

    // Create metering area with maximum weight
    Camera.Area meteringArea = new Camera.Area(scaledRect, 1000);

    // Create a list because setMeteringAreas() expects a List
    List<Camera.Area> meteringAreaList = new ArrayList<>();
    meteringAreaList.add(meteringArea);

    // Set metering area
    params.setMeteringAreas(meteringAreaList);
    mCamera.setParameters(params);
} else {
    // Not supported
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM