我正在尝试使用Android手机实现Spot Metering。 parameters.set(“自动曝光”,“点测光”);
但是,我对计量的工作方式感到有些困惑。如果我理解正确,Spot Metering的工作方式是选择一个用来设置曝光值的区域。
但是,在展平Camera.Parameters类并显示结果时,计量区域为(0,0,0,0,0)[意味着它具有零宽度,高度和重量],而自动曝光设置为正确地“点测光”。但是,在API中,“getMeteringAreas()”文档说计量区域的宽度和高度不能为零。
那么当测光面积为0时,我怎样才能使用“点测光”?我尝试将测光区域设置在右上角,但它对曝光没有任何影响。
这让我相信自动曝光=点测光与测光区域没有任何关系....这很奇怪。
如果情况并非如此,有人可以帮我理解我做错了什么吗?如果您需要更多信息,我将很乐意提供代码。
如果是这种情况(如计量区域与点测光无关),有人可以帮我弄清楚如何选择自动曝光测光仪的位置吗?我认为它默认为中心。
谢谢!
答案 0 :(得分:2)
MeteringAreas
参数用于自动对焦测光。
曝光测光模式没有Android api。您需要找到适当的未记录的参数名称和值来设置它(例如,通过native_getParameters
转储所有参数)。
例如,对于Samsung Galaxy Note 3参数名称为metering
,接受的值为center
,matrix
和spot
。所以你只需致电set("metering", "spot");
,它就会神奇地起作用。
答案 1 :(得分:1)
计量是与设备有关的事情。
在API级别14之前,没有用于管理计量的标准API,我认为有些品牌选择了自己的方式来管理它(在您的情况下:“自动曝光”关键字),但不是通过标准API 。 这就是您无法获得有效区域的原因。 parameters.flatten()中的计量区域(0,0,0,0,0)表示不支持计量区域(权重= 0),我猜getMaxNumMeteringAreas()返回0:
应该先调用getMaxNumMeteringAreas()来了解最大计量区域数。如果值为0,则不支持计量区域。
到目前为止,很少有设备支持计量区域(根据我的经验3/20)。
答案 2 :(得分:0)
此答案适用于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,并且投资回报率为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设置为测光区域。
您可以设置测光区域的权重(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
}