我想拍摄一张照片并使用 CameraX 从中心裁剪出一个 25x25 dp 的正方形。我读过使用 ImageCapture 可以进行裁剪,但不幸的是到目前为止几乎没有类似的例子。
val imageCaptureConfig = ImageCaptureConfig.Builder().apply {
setTargetAspectRatio(Rational(1, 1))
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
val imageCapture = ImageCapture(imageCaptureConfig)
btn_take_photo.setOnClickListener {
imageCapture.takePicture(
object : ImageCapture.OnImageCapturedListener() {
override fun onCaptureSuccess(image: ImageProxy?, rotationDegrees: Int) {
super.onCaptureSuccess(image, rotationDegrees)
// image manipulation here?
}
}
)
}
Run Code Online (Sandbox Code Playgroud) 我正在使用 Camera2 API 以流式(实时)方式使用 Firebase-ML 条形码解码器。我这样做的方法是设置一个 ImageReader 定期为我提供图像。完整图像是我的相机的分辨率,所以它很大 - 它是一个 12MP 相机。
条码扫描器在 Samsung S7 Edge 上处理图像大约需要 0.41 秒,因此我设置 ImageReaderListener 一次解码一个并丢弃任何后续帧,直到解码器完成。
我使用的图像格式是 YUV_420_888,因为这是文档推荐的,并且因为如果您尝试向 ML Barcode 解码器提供任何其他内容,它会抱怨(调试日志的运行时消息)。
所有这些都有效,但我认为如果我可以裁剪图像,效果会更好。我想让相机分辨率保持不变(以便我可以显示一个宽的 SurfaceView 以帮助用户将他的相机与条形码对齐),但我想给 Firebase 一个裁剪版本(基本上是一个中心矩形)。我所说的“更好地工作”主要是指“更快”,但我也想消除干扰(尤其是可能位于图像边缘的其他条码)。
这让我试图找出裁剪 YUV 图像的最佳方法,但我很惊讶地发现帮助很少。我在网上找到的大多数示例都执行多步骤过程,首先将 YUV 图像转换为 JPEG,然后将 JPEG 渲染为位图,然后对其进行缩放。这在我看来有几个问题
我四处寻找可能有帮助的 YUV 库。有一种叫做 libyuv-android 的东西,但它并不能完全按照 firebase-ml 想要的格式工作,而且它是一堆 JNI,让我担心跨平台问题。
我想知道是否还有其他人考虑过这个问题,并提出了一个更好的解决方案来在 Android 中裁剪 YUV_420_488 图像。我是否无法找到它,因为它是一个相对微不足道的操作?除其他事项外,还有步幅和填充需要关注。我不是图像/色彩专家,我有点觉得我不应该自己尝试这个,我特别关心的是我找到了一些在我的设备上有效但在其他人上无效的东西。
更新:这实际上可能没有实际意义。作为一项实验,我查看了从 ImageReader 返回的 Image。它是 ImageReader.SurfaceImage 的一个实例,它是一个私有(对 ImageReader)类。它也有一堆本地搭档。因此,唯一的选择可能是执行压缩/解压缩方法,这似乎很蹩脚。我唯一能想到的另一件事是自己决定只使用 Y 平面并从中制作位图,然后看看 …
我正在尝试使用 Firebase 的 MLKit 通过 Camerax 进行人脸检测。我很难让图像分析的图像代理大小与 PreviewView 的大小相匹配。对于图像分析和 PreviewView,我已将 setTargetResolution() 设置为 PreviewView 的宽度和高度。但是,当我在分析器中检查 Imageproxy 的大小时,它的宽度为 1920,高度为 1080。我的 PreviewView 宽度为 1080,高度为 2042。当我在 setTargetResolution() 中交换宽度和高度以进行图像分析时,imageproxy 中的宽度和高度都为 1088。我的预览视图也被锁定为纵向模式。
最终,我需要将原始图像代理数据和人脸点数据输入到 AR 代码中。因此,仅放大绘制面部点的图形叠加对我来说不起作用。
问:如果无法在 camerax 库中解决此问题,如何缩放从分析器返回的图像代理以匹配预览视图?
我正在使用 Java 和最新的 Camerax 库:
def camerax_version = "1.0.0-beta08"
通过 camera2 API,我们接收到格式为YUV_420_888的 Image 对象。然后我们使用以下函数转换为NV21:
private static byte[] YUV_420_888toNV21(Image image) {
byte[] nv21;
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
return nv21;
}
Run Code Online (Sandbox Code Playgroud)
虽然此函数与 配合良好cameraCaptureSessions.setRepeatingRequest,但在调用 时,我们会在进一步处理(在 JNI 端)中遇到分段错误cameraCaptureSessions.capture。两者都通过 ImageReader 请求 YUV_420_888 …