来自Android camera2 API的图像数据在Galaxy S5上翻转和挤压

我正在实施一个应用程序,使用相机的实时图像进行实时image processing。 这是工作,有限制,使用现在弃用的android.hardware.Camera; 改善灵活性和性能我想使用新的android.hardware.camera2 API。 我无法获得原始图像数据进行处理。 这是在三星Galaxy S5上。 (不幸的是,我没有另一个棒棒糖设备,方便在其他硬件上testing)。

我得到了总体框架(从“HdrViewFinder”和“Camera2Basic”样本中获得灵感),实时图像通过SurfaceTexture和GLSurfaceView绘制在屏幕上。 但是,我还需要访问图像数据(至less目前灰度级是很好的)用于定制image processing。 根据StreamConfigurationMap.isOutputSupportedFor(class)的文档,直接获取图像数据的推荐表面是ImageReader (正确的?)。

所以我设置了我的捕获请求:

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的onImageAvailablecallback中,我正在访问数据,如下所示:

 Image img = reader.acquireLatestImage(); ByteBuffer grayscalePixelsDirectByteBuffer = img.getPlanes()[0].getBuffer(); 

…但是(如上所述)实时图像预览正在工作,我得到的数据(或我的方式)出现问题。 根据

 mCameraInfo.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputFormats(); 

…应支持以下ImageFormats:NV21,JPEG,YV12,YUV_420_888。 我已经尝试了所有(插入上面的'格式'),都支持根据getOutputSizes(format)的设置分辨率,但没有一个给出了所需的结果:

  • NV21:ImageReader.newInstance抛出java.lang.IllegalArgumentException:不支持NV21格式
  • JPEG:这是行得通的,但是对于实时应用程序来说每个帧都要经过JPEG编码和解码似乎没有意义。
  • YV12和YUV_420_888:这是最奇怪的结果 – 我可以看到获取灰度图像,但它是垂直翻转 (是,翻转,不旋转!)和明显挤压 (水平缩放,但不是垂直)。

我在这里错过了什么? 是什么导致图像翻转和挤压? 我怎样才能得到一个几何正确的灰度缓冲区? 我应该使用不同types的表面(而不是ImageReader)?

任何提示赞赏。

Solutions Collecting From Web of "来自Android camera2 API的图像数据在Galaxy S5上翻转和挤压"

我发现一个解释(虽然不一定是一个令人满意的解决scheme):事实certificate,传感器arrays的长宽比是16:9(通过mCameraInfo.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); )find)。

至less在请求YV12 / YUV_420_888时,stream式传输器似乎不以任何方式裁剪图像,而是将其非均匀地缩放,以达到所请求的帧大小。 当请求16:9格式(不幸的是,其中只有两个更高分辨率的格式)时,图像具有正确的比例。 对我来说似乎有点奇怪 – 在请求JPEG,或使用等效的旧相机API函数或静止时,似乎不会发生这种情况。 而且我不确定非均匀缩放帧会有什么好处。

我觉得这不是一个真正令人满意的解决scheme,因为这意味着你不能依赖于输出格式列表,而是必须首先find传感器尺寸,find具有相同纵横比的格式,然后自己下载图像(如所须)…

我不知道这是预期结果还是S5的“特色”。 意见或build议仍然受欢迎。

我有同样的问题,并find了解决办法。 问题的第一部分是设置表面缓冲区的大小:

  // We configure the size of default buffer to be the size of camera preview we want. //texture.setDefaultBufferSize(width, height); 

这是图像偏斜的地方,而不是相机。 您应该将其注释掉,然后在显示图像时设置图像的放大倍数。

  int[] rgba = new int[width*height]; //getImage(rgba); nativeLoader.convertImage(width, height, data, rgba); Bitmap bmp = mBitmap; bmp.setPixels(rgba, 0, width, 0, 0, width, height); Canvas canvas = mTextureView.lockCanvas(); if (canvas != null) { //canvas.drawBitmap(bmp, 0, 0, null );//configureTransform(width, height), null); //canvas.drawBitmap(bmp, configureTransform(width, height), null); canvas.drawBitmap(bmp, new Rect(0,0,320,240), new Rect(0,0, 640*2,480*2), null ); //canvas.drawBitmap(bmp, (canvas.getWidth() - 320) / 2, (canvas.getHeight() - 240) / 2, null); mTextureView.unlockCanvasAndPost(canvas); } image.close(); 

你可以玩弄这些值来微调你的问题的解决scheme。