标签: android-camera2

Android Camera2拍摄图像倾斜

更新:这看起来与此相关: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 或自定义的)- …

android android-camera android-camera2 android-mediacodec

5
推荐指数
1
解决办法
3467
查看次数

图像读取器内将帧从 YUV_420_888 格式错误转换为 NV21

我配置了代码,以便使用对象和其余众所周知的APIYUV_420_888从设备的摄像头获取帧流。现在我需要将这些帧转换为像素格式并调用本机函数,该函数期望这种格式的帧执行某些计算。这是我在图像读取器回调中使用的代码,用于重新排列帧的字节:imageReadercamera2NV21

        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader mReader) {
                Image image = null;
                image = mReader.acquireLatestImage();
                if (image == null) {
                    return;
                }                           

                byte[] bytes = convertYUV420ToNV21(image);

                nativeVideoFrame(bytes);
                image.close();   
            }
        };

private byte[] convertYUV420ToNV21(Image imgYUV420) {

    byte[] rez;

    ByteBuffer buffer0 = imgYUV420.getPlanes()[0].getBuffer();
    ByteBuffer buffer1 = imgYUV420.getPlanes()[1].getBuffer();
    ByteBuffer buffer2 = imgYUV420.getPlanes()[2].getBuffer();

    int buffer0_size = buffer0.remaining();
    int buffer1_size = buffer1.remaining();
    int buffer2_size = buffer2.remaining();

    byte[] buffer0_byte = new byte[buffer0_size];
    byte[] buffer1_byte = new …
Run Code Online (Sandbox Code Playgroud)

android yuv pixelformat android-camera2

5
推荐指数
1
解决办法
2210
查看次数

使用camera2 API获取单张图像并用ImageView显示

我想使用 Camera2 API 从相机获取单个帧并使用 ImageView 显示它。我发现了一些密切的问题,例如

/sf/ask/1782359421/

我还查看了 Camera2Basic 示例,但它太复杂并且不完全是我所需要的。

我编写了代码,它基于我在网上看到的一些示例,应该可以实现,但它不起作用,我不明白为什么。

应用程序不会崩溃,但只是不在 ImageView 上显示任何内容。我在任何函数调用中都使用了日志消息,以便尝试保持 logcat 清晰。

另外,该应用程序是 logcat 说“该应用程序可能在后台做了太多工作......”我不明白这怎么可能,因为我制作了一个captureRequest而不是一个repeatingCaptureRequest.

这是代码和 logcat: 代码:

public class CameraImageReaderActivity extends AppCompatActivity {

private final static String TAG = "CAMERA_IMAGE_READY: ";
private ImageReader imageReader;
private String cameraId;
private CameraDevice camera;
private HandlerThread handlerThread;
private Handler handler;
private Surface imageReaderSurface;
private ImageView imageView;

private CameraDevice.StateCallback cameraStateCallback = new CameraDevice.StateCallback() {
    @Override
    public void onOpened(CameraDevice cameraDevice) {
        Log.d(TAG, "onOpend: CAMERA OPENED");
        camera = …
Run Code Online (Sandbox Code Playgroud)

android android-camera2

5
推荐指数
1
解决办法
7521
查看次数

如何在 onImageAvailable (android Camera2) 中从前置摄像头肖像模式转换和旋转原始 NV21 阵列图像 (android.media.Image)?

注意:我帖子中的所有信息仅适用于 Samsung Galaxy S7 设备。我不知道模拟器和其他设备的行为如何。

在 onImageAvailable 中,我将每个图像连续转换为 NV21 字节数组,并将其转发到需要原始 NV21 格式的 API。

这是我初始化图像读取器并接收图像的方式:

private void openCamera() {
    ...
    mImageReader = ImageReader.newInstance(WIDTH, HEIGHT,
            ImageFormat.YUV_420_888, 1); // only 1 for best performance
    mImageReader.setOnImageAvailableListener(
    mOnImageAvailableListener, mBackgroundHandler);
    ...
}

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
        = new ImageReader.OnImageAvailableListener() {

    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = reader.acquireLatestImage();
        if (image != null) {
            byte[] data = convertYUV420ToNV21_ALL_PLANES(image); // this image is turned 90 deg using front cam in portrait mode
            byte[] data_rotated = rotateNV21_working(data, …
Run Code Online (Sandbox Code Playgroud)

android portrait rotation front-camera android-camera2

5
推荐指数
1
解决办法
7650
查看次数

如何裁剪包含 Y'(亮度)的 byte[] 数组而不转换为位图

编辑:解决了!见下文。我需要裁剪从 Camera2 的 onImageAvailable 侦听器获取的图像(YUV422888 颜色空间)。我不想或不需要将其转换为位图,因为它对性能影响很大,而且我实际上对亮度感兴趣,而不是对 RGB 信息(包含在图像的平面 0 中)感兴趣。我想出了以下解决方案:

  1. 获取侦听器中 Camera2 提供的 Image 对象的 Plane 0 中包含的 Y' 信息。
  2. 将 Y' 平面转换.
  3. 将 byte[] 数组转换为二维 byte[][] 数组以进行裁剪。
  4. 使用一些for循环在所需的左、右、上、下坐标处进行裁剪。
  5. 将 2d byte[][] 数组折叠回 1d byte[] 数组out,其中包含裁剪后的亮度 Y' 信息。

不幸的是,第 4 点产生了损坏的图像。我究竟做错了什么?

在Camera2的onImageAvailableListener中(请注意,虽然我正在计算位图,但这只是为了看看发生了什么,因为我对位图/RGB数据不感兴趣):

               Image.Plane[] planes = image.getPlanes();
               ByteBuffer buffer = planes[0].getBuffer(); // Grab just the Y' Plane.
               buffer.rewind();
               byte[] data = new byte[buffer.capacity()];
               buffer.get(data);

               Bitmap bitmap = cropByteArray(data, image.getWidth(), image.getHeight()); // Just …
Run Code Online (Sandbox Code Playgroud)

arrays android image-processing yuv android-camera2

5
推荐指数
1
解决办法
1730
查看次数

当我尝试使用 ImageReader 获取每个 Camera2 帧时,出现“图像已关闭”

我尝试使用 Camer2 API 从相机获取每一帧以进行图像处理,但我得到一个FATAL EXCEPTION,上面写着

致命异常:主进程:com.example.avoor.camera2api,PID:2831 java.lang.IllegalStateException:图像已关闭

我成功地可以打开相机并将其发送到 TuxtureView 进行预览,但应用程序在涉及OnImageAvailableListener时崩溃。

这是使用的代码:

protected void createCameraPreview() {
    try {
        SurfaceTexture texture = textureView.getSurfaceTexture();
        assert texture != null;
        texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
        Surface surface = new Surface(texture);
        ImageReader reader = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 3);
        //reader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
        captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        captureRequestBuilder.addTarget(surface);
        captureRequestBuilder.addTarget(reader.getSurface());
        List<Surface> outputSurfaces = new ArrayList<>();
        outputSurfaces.add(reader.getSurface());
        outputSurfaces.add(surface);
        ///////////////////////////////////////////////////////////////////
        ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = null;
                try {
                    image = reader.acquireLatestImage();
                    final …
Run Code Online (Sandbox Code Playgroud)

android image-processing android-camera2

5
推荐指数
1
解决办法
5579
查看次数

Android 相机2 API。设置多个 ImageReader 表面会产生空白输出

我有一个camera2实现。当前的设置是,它使用纹理视图表面来显示实际的相机视图和ImageReader用于捕获图像的表面。

现在我也想捕获预览帧。所以我尝试添加一个新的ImageReader表面来捕获帧。但是当我添加该表面以createCaptureSession请求时,屏幕变为空白。可能出了什么问题?下面是我用来添加曲面的代码createCaptureSession

val surface = preview.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

val previewIRSurface = previewImageReader?.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

val captureSurface = captureImageReader?.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

try {
    val template = if (zsl) CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG else CameraDevice.TEMPLATE_PREVIEW

    previewRequestBuilder = camera?.createCaptureRequest(template)
            ?.apply { addTarget(surface) }
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

    val surfaces: ArrayList<Surface> = arrayListOf(surface, previewIRSurface, captureSurface)

    camera?.createCaptureSession(surfaces, sessionCallback, backgroundHandler)

} catch (e: CameraAccessException) {
    throw RuntimeException("Failed to start camera session")
}
Run Code Online (Sandbox Code Playgroud)

ImageReaders的初始化是这样的。

private fun prepareImageReaders() {

    val largestPreview = …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-camera2

5
推荐指数
1
解决办法
2892
查看次数

Camera2 在 Android API 29 中用两个物理流替换一个逻辑流

当Android 9(API 28)发布时,我很高兴地发现具有多个摄像头的手机的物理摄像头将被暴露,我曾因无法访问它们而感到非常沮丧。今天我偶然发现了 android Q文档,其中写道:

从 API 级别 29 开始,部分或所有物理相机可能无法独立向应用程序公开,在这种情况下,物理相机 ID 在 CameraManager.getCameraIdList() 中将不可用。但应用程序仍然可以通过调用CameraManager.getCameraCharacteristics(String)来查询物理相机的特征。

这个说法让我很困惑,难道Android正在回溯吗?改变的目的是什么?

我对在非常精细的水平上管理相机感兴趣,这一变化是否会阻止我做我今天能够使用 Android 9 做的事情?

上面说可以不再列出ID,但是仍然可以查询特征,那么在没有ID的情况下如何获取摄像机的特征呢?我想我们应该通过getPhysicalCameraIds()逻辑摄像机获取物理摄像机的 ID,但这是否意味着如果我们想使用“隐藏”摄像机,我们就必须测试一堆随机 ID 字符串?

在此输入图像描述

我们是否仍然能够在未暴露的物理相机上使用SessionConfiguration创建捕获会话?

有人可以解释一下吗?

android android-camera2

5
推荐指数
1
解决办法
4207
查看次数

React Native 中的 CameraX 视图 - 无法配置相机

我正在创建用于通过桥接进行本机反应的 cameraX 视图。(在 RN 中渲染正常视图。桥接流程很好。)PreviewView用于显示 CameraX 预览的相机馈送。我已成功实现预览,但不确定为什么预览未在 UI 上呈现。它只是一个空白屏幕。

让我知道 UI 原生组件的正确实现方式。我在活动中厌倦了同样的事情并且工作正常。我是 android 平台的新手。提前致谢!

https://groups.google.com/a/android.com/g/camerax-developers/c/G9jKs1Bo_CE 检查了这个。但不确定问题是否与重新布局有关。

从 NativeCameraView 类登录:

23:21:45.415 8026-8026/com.app D/PreviewView: Surface requested by Preview.
11-11 23:21:45.415 8026-8784/com.app D/UseCaseAttachState: All use case: [androidx.camera.core.Preview-ee9dbc80-160c-45e5-a38f-e68bc8f54373, androidx.camera.core.Preview-3e33af92-3cb6-4cb4-a0c3-dfb4e3c6cc8d] for camera: 0
11-11 23:21:45.415 8026-8784/com.app D/UseCaseAttachState: Active and attached use case: [androidx.camera.core.Preview-3e33af92-3cb6-4cb4-a0c3-dfb4e3c6cc8d] for camera: 0
11-11 23:21:45.416 8026-8784/com.app D/UseCaseAttachState: All use case: [androidx.camera.core.Preview-ee9dbc80-160c-45e5-a38f-e68bc8f54373, androidx.camera.core.Preview-3e33af92-3cb6-4cb4-a0c3-dfb4e3c6cc8d] for camera: 0
11-11 23:21:45.416 8026-8784/com.app D/UseCaseAttachState: Active and attached use case: [androidx.camera.core.Preview-ee9dbc80-160c-45e5-a38f-e68bc8f54373, androidx.camera.core.Preview-3e33af92-3cb6-4cb4-a0c3-dfb4e3c6cc8d] for camera: 0 …
Run Code Online (Sandbox Code Playgroud)

android react-native android-camera2 android-camerax

5
推荐指数
1
解决办法
513
查看次数

如何更改 android 中的 whiteBalance 增益值?

我想获取当前增益的值并更改 RGB 增益的值。

在 iOS 中,Apple提供了 setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:completionHandler.

- (void)setWhiteBalanceGains:(AVCaptureWhiteBalanceGains)gains
{
  NSError *error = nil;
  
  if ( [self.captureDevice lockForConfiguration:&error] ) {
    AVCaptureWhiteBalanceGains normalizedGains = [self normalizedGains:gains];
    [self.captureDevice setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:normalizedGains completionHandler:nil];
    [self.captureDevice unlockForConfiguration];
  }
  else {
    NSLog( @"Could not lock device for configuration: %@", error );
  }
}

- (AVCaptureWhiteBalanceGains)normalizedGains:(AVCaptureWhiteBalanceGains) g
{
  AVCaptureWhiteBalanceGains gains = g;
  gains.redGain = MAX(gains.redGain, 1.0f);
  gains.greenGain = MAX(gains.greenGain, 3.0f);
  gains.blueGain = MAX(gains.blueGain, 18.0f);
  
  return gains;
}
Run Code Online (Sandbox Code Playgroud)

我们如何使用cameraX在android中实现这一点?

COLOR_CORRECTION_GAINS

COLOR_CORRECTION_MODE

我已经检查了有关通道控制的文档。但是我们如何使用新控件更改色彩校正并重置 cameraX 预览?

android android-camera2 android-camerax

5
推荐指数
1
解决办法
120
查看次数