我正在构建扫描仪应用程序,并尝试从相机的预览回调中确定“预览质量”。如果环境太暗,我想自定义相机的地图AUTO_FLASH_MODE
。如何从实时相机预览中检测平均像素强度?
如何检测暗像素的平均值高?这意味着(预览中)我变暗,因此需要打开相机的闪光灯。
我正在构建扫描仪应用程序,并尝试从相机的预览回调中确定“预览质量”。如果环境太暗,我想自定义相机的地图AUTO_FLASH_MODE
。如何从实时相机预览中检测平均像素强度?
如何检测暗像素的平均值高?这意味着(预览中)我变暗,因此需要打开相机的闪光灯。
要么找出如何访问您的图像的像素值,并自己计算平均强度或使用任何图像处理库来这样做。
暗像素值较低,亮像素值较高。 您想要计算所有红色,绿色和蓝色值的平均值除以像素数的三倍。 定义何时打开闪光灯的阈值,但请记住,您必须获得新的曝光时间。 随着曝光时间的增加,图像噪点会变得更高,因此首选曝光时间增加。
我试过这种方法,但我认为它正在处理位图的不必要的时间,然后得到一个平均的屏幕色彩,
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Size cameraResolution = resolution;
PreviewCallback callback = this.callback;
if (cameraResolution != null && callback != null)
{
int format = camera.getParameters().getPreviewFormat();
SourceData source = new SourceData(data, cameraResolution.width, cameraResolution.height, format, getCameraRotation());
callback.onPreview(source);
final int[] rgb = decodeYUV420SP(data, cameraResolution.width, cameraResolution.height);
//Bitmap bmp = decodeBitmap(source.getData());
Bitmap bmp = Bitmap.createBitmap(rgb, cameraResolution.width, cameraResolution.height, Bitmap.Config.ARGB_8888);
if (bmp != null)
{
//bmp = decodeBitmap(source.getData());
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
// bmp.compress(Bitmap.CompressFormat.JPEG, 70, bytes);
Bitmap resizebitmap = Bitmap.createBitmap(bmp,
bmp.getWidth()/2, bmp.getHeight()/2, 60, 60);
int color = getAverageColor(resizebitmap);
Log.i("Color Int", color + "");
// int color = resizebitmap.getPixel(resizebitmap.getWidth()/2,resizebitmap.getHeight()/2);
String strColor = String.format("#%06X", 0xFFFFFF & color);
//String colorname = sColorNameMap.get(strColor);
Log.d("strColor", strColor);
Log.i("strColor", color + "");
if(!mIsOn)
{
if (color == -16777216 || color < -16777216)//minimum color code (full dark)
{
mIsOn = true;
setTorch(true);
Log.d("Yahooooo", "" + color);
}
}
Log.i("Pixel Value",
"Top Left pixel: " + Integer.toHexString(color));
}
}
else
{
Log.d(TAG, "Got preview callback, but no handler or resolution available");
}
}
}
private int[] decodeYUV420SP(byte[] yuv420sp, int width, int height)
{
final int frameSize = width * height;
int rgb[]=new int[width*height];
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;
rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) &
0xff00) | ((b >> 10) & 0xff);
}
}
return rgb;
}
private int getAverageColor(Bitmap bitmap)
{
int redBucket = 0;
int greenBucket = 0;
int blueBucket = 0;
int pixelCount = 0;
for (int y = 0; y < bitmap.getHeight(); y++) {
for (int x = 0; x < bitmap.getWidth(); x++) {
int c = bitmap.getPixel(x, y);
pixelCount++;
redBucket += Color.red(c);
greenBucket += Color.green(c);
blueBucket += Color.blue(c);
// does alpha matter?
}
}
int averageColor = Color.rgb(redBucket/pixelCount, greenBucket
/pixelCount, blueBucket/pixelCount);
return averageColor;
}
我不是机器人专家。我确定有一种方法可以获取预览图像的字节数据。无论如何,这不是你的字节数组“数据”吗?你使用它作为位图解码的输入.... 如果不是,我建议你在这里创建一个新的简单问题: 如何从Android相机或谷歌获取像素值...我想你的标题是一个有点模糊。 – Piglet
其实我想自定义相机的AUTO_FLASH_MODE,我发现任何黑暗的环境(以像素为单位),然后打开肉体直到我的扫描仪打开。 –
我删除了** Flash **标签(在使用之前请阅读标签的说明)。无论如何,所有像素的强度值都是0到255 ......所以128是完全亮(255)和暗(0)之间的一半。决定什么数字意味着“太暗”,然后通过在代码中使用for循环来检查预览图像中的像素值。查看直方图,因为这可能比检查每个像素更有用和更快。 –
@ VC.One如何查看直方图比检查每个像素更快。你如何计算直方图? – Piglet