我正在实现一个应用程序,该应用程序对来自相机的实时图像进行实时图像处理。它使用现已弃用的 android.hardware.Camera 进行工作,但有限制;为了提高灵活性和性能,我想使用新的 android.hardware.camera2 API。然而,我在获取原始图像数据进行处理时遇到了麻烦。这是在三星 Galaxy S5 上。 (不幸的是,我没有另一个 Lollipop 设备可以方便地在其他硬件上进行测试)。
我得到了整个框架(受到“HdrViewFinder”和“Camera2Basic”示例的启发)的工作,并且实时图像通过 SurfaceTexture 和 GLSurfaceView 在屏幕上绘制。但是,我还需要访问图像数据(仅灰度就可以,至少目前如此)以进行自定义图像处理。根据文档StreamConfigurationMap.isOutputSupportedFor(类),直接获取图像数据的推荐表面为图像读取器(正确的?)。
所以我将捕获请求设置为:
mSurfaceTexture.setDefaultBufferSize(640, 480);
mSurface = new Surface(surfaceTexture);
...
mImageReader = ImageReader.newInstance(640, 480, format, 2);
...
List<Surface> surfaces = new ArrayList<Surface>();
surfaces.add(mSurface);
surfaces.add(mImageReader.getSurface());
...
mCameraDevice.createCaptureSession(surfaces, mCameraSessionListener, mCameraHandler);
在 ImageReader 的 onImageAvailable 回调中,我按如下方式访问数据:
Image img = reader.acquireLatestImage();
ByteBuffer grayscalePixelsDirectByteBuffer = img.getPlanes()[0].getBuffer();
...但是,虽然(如上所述)实时图像预览正在工作,但我在此处获取的数据(或我获取数据的方式)存在问题。根据
mCameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputFormats();
...应支持以下图像格式:NV21、JPEG、YV12、YUV_420_888。我已经尝试了所有(插入上面的“格式”),所有都支持根据设置的分辨率getOutputSizes(format)
,但没有一个给出期望的结果:
- NV21:ImageReader.newInstance 抛出 java.lang.IllegalArgumentException:不支持 NV21 格式
- JPEG:这确实有效,但对于实时应用程序来说,对每一帧进行 JPEG 编码和解码似乎没有意义......
- YV12 和 YUV_420_888:这是最奇怪的结果——我可以看到得到灰度图像,但它是垂直翻转(是的,翻转,而不是旋转!)并且显着squished(在水平方向上显着缩放,但在垂直方向上没有缩放)。
我在这里缺少什么?是什么导致图像翻转和压扁?如何获得几何上正确的灰度缓冲区?我应该使用不同类型的表面(而不是 ImageReader)吗?
任何提示表示赞赏。