Android Camera2 拍照后图像倾斜

5
更新:看起来与此相关: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矩阵变换以正确绘制。但是-我该怎么做?
注意:使用旧的相机API,具有完全相同的“预览大小”和相同的表面作为目标(无论是MediaCodec的还是自定义的)-一切都很好!但是我不能使用旧的相机API,因为它已被弃用,并且似乎具有最大捕获大小为1080p,而Camera2 API超出了这一范围,我需要支持4k录制。

你能找到解决方法吗? - Edmund Rojas
不。我学会了将其视为一个BUG并继续前进。谷歌总是会说这是三星的问题,而三星并不关心模糊平台错误或他们的Camera2 API实现,只要人们盲目购买他们最新的旗舰产品。 - Adrian Crețu
我最终在Marshmellow下将三星设备列入白名单,使用camera1,似乎三星没有费心更新其相机以与camera2兼容,直到Marshmellow。 - Edmund Rojas
@AdrianCrețu,我只是想知道你是如何在camera2预览上绘制的...我尝试过但未能成功。你能帮助我吗? - Raut Darpan
@AdrianCrețu,你在这里帮忙吗? - Raut Darpan
显示剩余4条评论
2个回答

2

我遇到了类似的问题,使用API级别为21的模型SM-A7009和传统的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的bug。

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

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


1
正如被接受的答案所指出的那样,这是供应商方面的一个错误,通常发生在相机需要输出不同尺寸(例如具有其他宽高比的预览)的情况下,从而破坏了缩放。更糟糕的是,一些设备甚至会在Camera2工作线程内部崩溃(尝试使用错误参数进行裁剪时出现无效参数异常)。这绝对是我遇到过的#1无法解决的崩溃。 - Adrian Crețu
2
在我的情况下,即使预览和图像阅读器的纵横比相同,将预览缓冲区大小设置为“SurfaceTexture”仍然无法正常工作。Camera2框架仍会覆盖其中一个尺寸为“1440x1080、640x480、320x240”的尺寸。 - alijandro

1
所以,是的,这是那些三星设备上的一个错误。通常情况下,当您要求输出多个不同的宽高比时,设备特定的相机代码在正确裁剪和缩放所有宽高比方面会出现问题。您可以通过确保所有请求的大小具有相同的宽高比来避免这种情况发生。分辨率可能实际上是您所要求的 - 但它被错误地缩放了(您可以使用问题尺寸的ImageReader进行测试,在那里您可以得到一个显式的缓冲区)。我们正在向Android合规性测试中添加额外的测试,以尝试确保这些类型的拉伸输出不会继续发生。

@ArkadyGamza - 既然我们谈论的是Surface,你怎么知道相机选择了什么?3264x2448与640x480具有相同的宽高比,因此不会出现扭曲。对我来说,Nexus 5在这方面表现良好。 - Adrian Crețu
@EddyTalvala - 我理解这是AOSP(或三星?)在输出到多个具有不同输出纵横比的表面时出现的错误。不幸的是,这正是我为预览+编码目的所做的事情。我认为你是第一个正确解释这个问题的人,所以我会将其标记为答案。 - Adrian Crețu
这不是AOSP的错误,那样会更容易修复。这是一些特定设备摄像头实现的错误(AOSP只告诉相机硬件“以 A、B 和 C 的尺寸给我们这些输出”)。通常是因为在幕后,它们的摄像头管道中只有一些图像缩放单元,因此如何执行给定一组输出的映射可能会变得复杂。他们错过了测试某些排列组合。 - Eddy Talvala

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接