【问题标题】:Manipulating android camera frame data in JNI在 JNI 中操作 android 相机帧数据
【发布时间】:2013-05-31 05:33:22
【问题描述】:

我正在尝试使用 NDK 进行一些图像处理。我没有使用opencv。

我对 Android 还很陌生,所以我是分步进行的。我首先编写了一个简单的应用程序,它可以让我从相机捕获视频并将其显示到屏幕上。我已经完成了。

然后我尝试在本机中操作相机数据。但是,onPreviewFrame 使用字节数组来捕获帧信息。这是我的代码 -

public void onPreviewFrame(byte[] arg0, Camera arg1) 
{
  if (imageFormat == ImageFormat.NV21)
  {
    if ( !bProcessing )
    {
      FrameData = arg0;
      mHandler.post(callnative);
    }
  }
}

而callnative runnable就是这样——

private Runnable callnative = new Runnable() 
{
  public void run() 
  {    
    bProcessing = true;
    String returnNative = callTorch(MainActivity.assetManager, PreviewSizeWidth,           PreviewSizeHeight, FrameData, pixels);
    bitmap.setPixels(pixels, 0, PreviewSizeWidth, 0, 0, PreviewSizeWidth, PreviewSizeHeight);
    MycameraClass.setImageBitmap(bitmap);
    bProcessing = false;
  }
};

问题是,我需要在本机中使用 FrameData 作为浮点数据类型。但是,它是字节数组的形式。我想知道帧数据是如何存储的。这是一个二维字节数组吗?那么相机返回一个 8 位图像并将其存储为 640x480 字节?如果是这样,C 以什么形式解释这种字节数据类型?我可以简单地将其转换为浮点数吗?我有这个原生的 -

jbyte *nativeData;
nativeData = (env)->GetByteArrayElements(NV21FrameData,NULL);      
__android_log_print(ANDROID_LOG_INFO, "Nativeprint", "nativedata is: %d",(int)nativeData[0]);

但是,这会打印出 -22,这让我相信我正在尝试打印出一个指针。不过我不知道为什么会这样。

我将不胜感激。

【问题讨论】:

    标签: android android-ndk android-camera


    【解决方案1】:

    您将无法从像素缓冲区中获取任何浮点数据类型。数据以 bytes 为单位,在 C 中是 char 数据类型。

    所以: jbyte *nativeData = (env)->GetByteArrayElements(NV21FrameData,NULL);

    与此相同: char *nativeData = (char *)((env)->GetByteArrayElements(NV21FrameData, NULL));

    数据存储为一维数组,因此您将通过宽度、高度以及 x 和 y 计算来检索每个像素。

    还请记住,您的示例中的预览相机帧在 YUV420sp 中,这意味着您需要先将数据从 YUV 转换为 RGB,然后才能将其设置为位图。

    【讨论】:

    • 我在网上找到了一段将yuv转换为rgb的代码。这是一个名为 decodeYUV420sp.c 的文件。它使用接收 jbyte 并将它们类型转换为整数的函数,然后再处理它们并将 R、G 和 B 通道作为整数类型返回。他们是怎么做到的?
    • 认为典型的 YUV 转换中字节和整数之间的转换实际上并没有任何数据类型变化。只是您决定读取像素数据的方式,因此例如 1 个 int 被安排为包含每个颜色分量 (A-R-G-B) 的 4 个字节。如何读取 YUV 字节数组取决于数据的排列方式。做一个简单的谷歌搜索会给你几个不同的例子,用于在 android 中进行 YUV 转换。请记住,YUV420sp(半平面)与 YUV420p(平面)不同
    • 好的那么相机如何以字节的形式返回数据呢?一个像素需要有一些价值。有很多很多可能的格式。相机帧中最左上角的像素是完全黑色的。这将具有什么价值?在标准 jpeg 或 png 中,它是 0。我想弄清楚的是当 Android 将它作为字节数组返回时它的值是什么?此外,图像是二维的。为什么Android返回一维字节数组?
    • 在“PreviewCallback”中,相机将以您在实现 PreviewCallback 接口的 SurfaceView 的 SurfaceHolder 中指定的格式返回字节。所以你必须将它设置为 yourSurfaceView.getHolder().setFormat(ImageFormat.NV21);将其设置为 NV21 将使预览数据在 YUV420sp 中。虽然 ImageFormat 有多种类型,但目前仅支持 NV21 和 YV12 两种预览格式,是所有设备通用的 NV21。关于最终拍摄照片时的相机拍摄本身,字节数组实际上返回一个普通的Jpeg。
    • 关于一维字节数组,这比返回二维数组(或数组的数组)效率更高,如果知道图像的宽度和高度,读取一维数组完全没有困难。不要误以为 2D 图像应该始终以 2D 数组表示,这是不正确的。如果您知道宽度和高度,那么在遍历数组时,您就知道“宽度”是从左到右读取的字节数,而“高度”是读取字节“宽度”的次数从上到下,因此您可以有 2 个嵌套的“for”循环来读取数据。
    猜你喜欢
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多