【问题标题】:Android Camera2 capture image skewedAndroid Camera2捕获图像倾斜
【发布时间】:2016-03-07 10:41:12
【问题描述】:

更新:这看起来与此有关:Image data from Android camera2 API flipped & squished on Galaxy S5 - 我认为这是一个错误,因为 Nexus 5/6 可以正常工作,并且需要获得完整的传感器尺寸和然后手动裁剪以达到所需的纵横比,最好不要使用“支持”的输出尺寸!

问题:

  1. 使用 Camera2 API 获取相机的特征,并提取适合 MediaCodec.class 的输出大小
  2. 使用合适的摄像机输出尺寸之一创建 MediaCodec 输入表面。将输出提供给一些 MediaMuxer 或其他任何东西,以查看输出。
  3. 使用编解码器创建的表面作为目标启动相机捕获请求。
  4. 编解码器输出的大小正确。但结果因设备而异:

    • Nexus 5/6:在 Android 5/6 上一切正常。
    • Android 5.1 的三星平板:某些分辨率下,图像明显拉伸,说明摄像头输出分辨率与表面尺寸不匹配。开始旋转相机时变得非常明显 - 图像变得越来越倾斜,因为它没有与 X/Y 轴对齐。对于其他一些分辨率,输出正常。这里没有与大小或纵横比相关的模式。

没问题,有人会说。也许表面不是完全按照指定的宽度和高度创建的,或者其他什么(即使输出大小是专门为 MediaCodec.class 目标提取的)。

因此,我创建了一个 OpenGL 上下文,为其生成了一个纹理,一个 SurfaceTexture,将其默认缓冲区大小设置为相机输出大小,并使用该纹理创建了一个 Surface。我不会深入讨论将其绘制到 TextureView 或返回到 MediaCodec 的 EGL 表面的血腥细节。结果是相同的 - Camera2 捕获请求仅针对某些分辨率输出失真图像。 深入挖掘:在 updateTexImage 之后立即在 SurfaceTexture 上调用 getTransformMatrix - 正如预期的那样,矩阵始终是单位矩阵。

所以,这里真正的问题是相机没有以提供的目标表面大小进行捕捉。因此,解决方案是获取相机正在捕获的 实际 大小,其余的是纯 GL 矩阵变换以正确绘制。但是 - 我如何得到它?

注意:使用旧的 Camera API,具有完全相同的“预览尺寸”和 相同 表面作为目标(MediaCodec 或自定义) - 一切都很好!但是我不能使用旧的相机 API,因为它已被弃用,而且似乎最大捕获大小为 1080p,而 Camera2 API 超出了这个范围,我需要支持 4k 录制。

【问题讨论】:

  • 你能找到解决办法吗?
  • 没有。我学会了忍受它作为一个 BUG 并继续前进。谷歌总是会说这是三星的问题,只要人们盲目地购买他们最新的旗舰产品,三星就不会关心模糊的平台错误或他们的 Camera2 API 实现。
  • 我最终将 Marshmellow 下的三星设备列入白名单以使用 camera1 代替,三星似乎直到 Marshmellow 才费心更新其相机以与 camera2 一起使用
  • @AdrianCrețu 嘿,我能知道你是如何通过 openGl 创建camera2 perview 的吗?我需要帮助
  • @RautDarpan - 我已经生成了一个 OpenGL 纹理并使用它来创建输入到相机捕获请求中的 SurfaceTexture/Surface。其余的是通常的 OpenGL 操作。当然,如果您询问如何进一步操作,细节可能会变得复杂,但这是核心。

标签: android android-camera android-mediacodec android-camera2


【解决方案1】:

我遇到了类似的问题,型号 SM-A7009 使用 api 级别 21,旧式 camera2 设备。

预览被拉伸,surfaceTexture.setDefaultBufferSize 不起作用,框架将在预览开始时覆盖这些值。

StreamConfigurationMap.getOutputSizes(SurfaceTexture.class) 报告的预览尺寸并非全部支持。

仅支持其中三个。

$ adb shell dumpsys media.camera |grep preview-size
preferred-preview-size-for-video: 1920x1080
preview-size: 1440x1080
preview-size-values: 1920x1080,1440x1080,1280x720,1056x864,960x720,880x720,800x480,720x480,640x480,528x432,352x288,320x240,176x144

系统转储信息中列出了很多预览尺寸,全部查看后发现只支持1440x1080640x480320x240

支持的预览尺寸都具有1.33333 比率。它们与CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE 报告的比率相同。

所以我认为这是一些三星设备在 API 21 中使用旧式 camera2 api 的错误。

解决方案是让这些设备使用已弃用的相机 API。

希望对任何到达这里的人有所帮助。

【讨论】:

  • 正如接受的答案指出的那样,这是供应商的一个错误,通常发生在相机还需要输出 不同 尺寸(如具有其他纵横比的预览)时),弄乱了缩放比例。情况变得更糟,因为某些设备甚至在 Camera2 工作线程内出现异常(尝试使用错误参数裁剪的无效参数)而崩溃。 这绝对是我遇到的第一个无法解决的崩溃问题。
  • 在我的场景中,即使预览和图像阅读器的纵横比相同,设置为SurfaceTexture 的预览缓冲区大小仍然不起作用。 camera2 框架仍然使用 1440x1080, 640x480, 320x240 的大小之一覆盖。
【解决方案2】:

是的,这是三星设备上的一个错误。

当您要求输出多个不同的纵横比时,通常会发生这种情况,并且特定于设备的相机代码在正确裁剪和缩放所有这些时会自行跳闸。您可以通过确保所有请求的尺寸具有相同的纵横比来避免这种情况。

分辨率实际上可能是您所要求的 - 但它的缩放比例不正确(您可以使用有问题的大小的 ImageReader 进行测试,在那里您可以获得一个可以戳的显式缓冲区。)

我们正在向 Android 合规性测试添加额外的测试,以确保此类延伸输出不会继续发生。

【讨论】:

  • @ArkadyGamza - 你怎么知道“相机选择”,因为我们毕竟在谈论 Surface?并且 3264x2448 与 640x480 的纵横比相同,因此不会出现倾斜。 Nexus 5 在这方面对我来说效果很好。
  • @EddyTalvala - 所以我知道这是 AOSP(或三星?)中的一个错误,当输出到多个表面时,具有不同的输出纵横比。不幸的是,这正是我正在做的,用于预览+编码目的。我认为您是第一个真正解释这一点的人,所以我将其标记为答案。
  • 这不是 AOSP 错误;那会更容易修复。这是一些特定于设备的相机实现的错误(AOSP 只是告诉相机硬件“给我们这些尺寸为 A、B 和 C 的 X 输出”。通常这是因为在引擎盖下,它们的内部只有一些图像缩放单元相机管道,因此如何进行一组给定输出的映射可能会变得复杂。他们错过了一些排列的测试。
猜你喜欢
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多