如何在 Camera2 API Android 5.0 中获取单个预览帧?
Posted
技术标签:
【中文标题】如何在 Camera2 API Android 5.0 中获取单个预览帧?【英文标题】:How to get single preview frame in Camera2 API Android 5.0? 【发布时间】:2015-06-07 10:28:26 【问题描述】:我正在尝试使用 Camera2 API 为 QR 码扫描功能获取 预览框架。在旧的 Camera API 中,它很简单:
android.hardware.Camera mCamera;
...
mCamera.setPreviewCallback(new Camera.PreviewCallback()
@Override
public void onPreviewFrame(byte[] data, Camera camera)
// will be invoked for every preview frame in addition to displaying them on the screen
);
但是,我无法找到一种方法来使用 新 Camera2 API 实现这一目标。我想接收多个可以处理的帧 - 最好的方法是接收旧 API 中的字节数组。任何想法如何做到这一点?
【问题讨论】:
看看这个问题。 ***.com/questions/25462277/… github.com/Gutyn/camera2QRcodeReader 我发布了这个例子,它使用最新的android2相机API来读取二维码。享受 【参考方案1】:有点晚,但总比没有好:
通常TextureView
用于显示相机的预览。每次表面变化时,您都可以使用TextureView.SurfaceTextureListener
获取回调。 TextureView
确实提供了一个方法getBitmap(Bitmap)
,您可以使用它来获得与TextureView
相同大小的预览帧。
您可以使用this Google sample 作为起点。只需更新 surfaceTextureListener,如下所示:
private val surfaceTextureListener = object : TextureView.SurfaceTextureListener
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int)
openCamera(width, height)
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int)
configureTransform(width, height)
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) = true
override fun onSurfaceTextureUpdated(texture: SurfaceTexture)
// Start changes
// Get the bitmap
val frame = Bitmap.createBitmap(textureView.width, textureView.height, Bitmap.Config.ARGB_8888)
textureView.getBitmap(frame)
// Do whatever you like with the frame
frameProcessor?.processFrame(frame)
// End changes
【讨论】:
【参考方案2】:使用下面的代码来做到这一点。
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraDevice.getId());
Size[] jpegSizes = null;
if (characteristics != null)
jpegSizes = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);
int width = 480;//480x320
int height = 320;
if (jpegSizes != null && 0 < jpegSizes.length)
width = jpegSizes[0].getWidth();
height = jpegSizes[0].getHeight();
ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
List<Surface> outputSurfaces = new ArrayList<Surface>(2);
outputSurfaces.add(reader.getSurface());
outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
captureBuilder.addTarget(reader.getSurface());
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
// Orientation
int rotation = ((Activity) context).getWindowManager().getDefaultDisplay().getRotation();
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));
final File file = getFileDir();
ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener()
@Override
public void onImageAvailable(ImageReader reader)
Image image = null;
try
image = reader.acquireLatestImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.capacity()];
buffer.get(bytes);
save(bytes);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (image != null)
image.close();
private void save(byte[] bytes) throws IOException
OutputStream output = null;
try
output = new FileOutputStream(file);
output.write(bytes);
finally
if (null != output)
output.close();
;
reader.setOnImageAvailableListener(readerListener, mBackgroundHandler);
catch (CameraAccessException e)
e.printStackTrace();
【讨论】:
cameraDevice 是从哪里来的? 您正在展示如何捕获图像,问题是如何在捕获图像之前获取预览帧,例如增强现实 将 imagereader 作为 capturerequestbuilder 的目标会令人难以置信地减慢帧速率,不知道如何提高它以上是关于如何在 Camera2 API Android 5.0 中获取单个预览帧?的主要内容,如果未能解决你的问题,请参考以下文章
Android:如何检查设备是不是实现了 Camera2 api 功能?