在 Android 中拍摄一张照片,然后使用 ImageAnalyzer 对其进行处理
Capture a picture in Android, and work with it using the ImageAnalyzer
我正在尝试实施一种解决方案,该解决方案能够从 phone 的相机中捕捉图片,然后操作图片(对其进行处理)并快速重复此过程 N 次。
我已经使用 imageCapture.takePicture
方法实现了这一点,但是当尝试对 N 张图片实施相同的过程时,onCaptureSuccess
方法每 ~500 毫秒被调用一次(在坚固的三星设备上) .捕获和保存图片的过程对我来说持续时间太长。我需要它比 500 毫秒更快。
我正在寻找使用 imageAnalyzer
class 来实现它,并使用了类似于这样的代码:
private class CameraAnalyzer implements ImageAnalysis.Analyzer {
@Override
public void analyze(@NonNull ImageProxy image) {
ByteBuffer bb = image.getPlanes()[0].getBuffer();
byte[] buf = new byte[bb.remaining()];
bb.get(buf);
//raw - data container
raw = buf;
//runnable - operate the picture
runnable.run();
image.close();
}
}
但是我收到 buf
的 NULL 并且图片总是空的。 bb.rewind()
也没有帮助。
在被告知图片是 RAW 格式,因此需要将其转换为位图后,我使用以下代码完成了:
ImageProxy.PlaneProxy[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * image.getWidth();
Bitmap bitmap = Bitmap.createBitmap(image.getWidth()+rowPadding/pixelStride,
image.getHeight(), Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
但是在执行 copyPixelsFromBuffer
时我遇到了这个问题:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.strujomeri, PID: 24466
java.lang.RuntimeException: Buffer not large enough for pixels
如何在imageAnalyzer
中得到我想要的图片,并且有内容
在 byte[]
格式中用它做什么我想要什么?
默认的 image
格式是 YUV_420_888 并且由于您的缓冲区只有一个平面(亮度 (Y) 平面),缓冲区的像素只有一个 byte
尺寸。
copyPixelsFromBuffer
假定 buffer
与位图的颜色 space 相同,因此当您将位图格式设置为 ARGB_8888 时,它正在寻找每个像素 4 个字节,而不是你给它的每个像素 1 个字节。
我没用过这个,但是这个 page 有一个 ImageProxy.toBitmap
示例,可以通过 Jpeg 将 YUV 转换为位图(如果您只想要 Jpeg,可以跳过最后一步)
我还看到另一个 method 不是通过 Jpeg 而是直接将 YUV 的颜色space 更改为位图。
您当然可以更改为唯一的其他颜色 space ImageAnalysis 支持 ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888
这需要更长的时间才能捕获,因为它需要转换并且仍然不是位图的正确格式
我正在尝试实施一种解决方案,该解决方案能够从 phone 的相机中捕捉图片,然后操作图片(对其进行处理)并快速重复此过程 N 次。
我已经使用 imageCapture.takePicture
方法实现了这一点,但是当尝试对 N 张图片实施相同的过程时,onCaptureSuccess
方法每 ~500 毫秒被调用一次(在坚固的三星设备上) .捕获和保存图片的过程对我来说持续时间太长。我需要它比 500 毫秒更快。
我正在寻找使用 imageAnalyzer
class 来实现它,并使用了类似于这样的代码:
private class CameraAnalyzer implements ImageAnalysis.Analyzer {
@Override
public void analyze(@NonNull ImageProxy image) {
ByteBuffer bb = image.getPlanes()[0].getBuffer();
byte[] buf = new byte[bb.remaining()];
bb.get(buf);
//raw - data container
raw = buf;
//runnable - operate the picture
runnable.run();
image.close();
}
}
但是我收到 buf
的 NULL 并且图片总是空的。 bb.rewind()
也没有帮助。
在被告知图片是 RAW 格式,因此需要将其转换为位图后,我使用以下代码完成了:
ImageProxy.PlaneProxy[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * image.getWidth();
Bitmap bitmap = Bitmap.createBitmap(image.getWidth()+rowPadding/pixelStride,
image.getHeight(), Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
但是在执行 copyPixelsFromBuffer
时我遇到了这个问题:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.strujomeri, PID: 24466
java.lang.RuntimeException: Buffer not large enough for pixels
如何在imageAnalyzer
中得到我想要的图片,并且有内容
在 byte[]
格式中用它做什么我想要什么?
默认的 image
格式是 YUV_420_888 并且由于您的缓冲区只有一个平面(亮度 (Y) 平面),缓冲区的像素只有一个 byte
尺寸。
copyPixelsFromBuffer
假定 buffer
与位图的颜色 space 相同,因此当您将位图格式设置为 ARGB_8888 时,它正在寻找每个像素 4 个字节,而不是你给它的每个像素 1 个字节。
我没用过这个,但是这个 page 有一个 ImageProxy.toBitmap
示例,可以通过 Jpeg 将 YUV 转换为位图(如果您只想要 Jpeg,可以跳过最后一步)
我还看到另一个 method 不是通过 Jpeg 而是直接将 YUV 的颜色space 更改为位图。
您当然可以更改为唯一的其他颜色 space ImageAnalysis 支持 ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888
这需要更长的时间才能捕获,因为它需要转换并且仍然不是位图的正确格式