我想分析图像帧流并对其进行一些计算。但是,使用CameraX时,在相机绑定上,ImageAnalysis实现类似乎仅被调用一次。
我的问题是:如何在连续的图像流上进行分析-从概念上讲类似于视频流?
以下是我的相机,预览和分析设置代码:
private void setPreview() {
ListenableFuture<ProcessCameraProvider> instance = ProcessCameraProvider.getInstance(this);
Activity self = this;
instance.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = instance.get();
Preview preview = new Preview.Builder().build();
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().build();
imageAnalysis.setAnalyzer(Executors.newFixedThreadPool(1),
new ImageAnalyser(new CameraLogListener() {
@Override
public void log(String msg) {
Log.e("Camera log", msg);
}
}));
CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
cameraProvider.unbindAll();
Camera camera = cameraProvider.bindToLifecycle(((LifecycleOwner)self), cameraSelector, preview, imageAnalysis);
preview.setSurfaceProvider(
((PreviewView)findViewById(R.id.cameraTextureView)).createSurfaceProvider(camera.getCameraInfo()));
} catch (ExecutionException e) {
e.printStackTrace();
Log.e("TAG", "Use case binding failed", e);
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("TAG", "Use case binding failed", e);
}
}, ContextCompat.getMainExecutor(this));
}
以下是我的ImageAnalysis实现类:
private class ImageAnalyser implements ImageAnalysis.Analyzer {
CameraLogListener listener;
public ImageAnalyser(CameraLogListener listener) {
this.listener = listener;
}
@Override
public void analyze(@NonNull ImageProxy image) {
ByteBuffer imageBuffer = image.getPlanes()[0].getBuffer();
StringBuilder sb = new StringBuilder();
sb.append("format:" + image.getFormat()).append("\n")
.append(image.getWidth() + " x " + image.getHeight()).append("\n\n");
for (int i=0; i<image.getPlanes().length; i++) {
sb.append("pixel stride:").append(image.getPlanes()[i].getPixelStride())
.append("\nrow stride:").append(image.getPlanes()[i].getRowStride())
.append("\n");
}
listener.log(sb.toString());
}
}
我发现了问题。在
的末尾 public void analyze(@NonNull ImageProxy image) {}
方法,您需要调用image.close()。引用documentation:
[从analytics()返回之前,请通过调用image.close()关闭图像引用,以避免阻止生成其他图像(导致预览停顿),并避免潜在的图像丢失。该方法必须完成分析或进行复制,而不是将图像参考传递到分析方法之外。