【问题标题】:Display the YUV value from live camera preview Android从实时相机预览 Android 中显示 YUV 值
【发布时间】:2018-03-10 00:38:54
【问题描述】:

这个问题已经被问过很多次了,但我似乎找不到我想要的东西。 我正在尝试创建一个相机应用程序,当我将相机指向某种颜色时,我想将 YUV 或 RGB 值显示到日志中。对于 RGB 或对应的 YUV 颜色格式,值必须是 0...255 范围。我可以管理它们之间的转换,因为堆栈溢出有很多这样的例子。但是,我无法将这些值存储到 3 个单独的变量中并在日志中显示它们。

到目前为止,我已经设法得到了

package com.example.virus.bpreader;

public class CaptureVideo extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {

private SurfaceHolder mHolder;
private Camera mCamera;
private int[] pixels;

public CaptureVideo(Context context, Camera cameraManager) {
    super(context);

    mCamera = cameraManager;
    mCamera.setDisplayOrientation(90);

    //get holder and set the class as callback
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {

    //when the surface is created, let the camera start the preview
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
        mCamera.cancelAutoFocus();

        Camera.Parameters params = mCamera.getParameters();
        //get fps
        params.getSupportedPreviewFpsRange();
        //get resolution
        params.getSupportedPreviewSizes();
        //stop auto exposure
        params.setAutoExposureLock(false);

        // Check what resolutions are supported by your camera
        List<Camera.Size> sizes = params.getSupportedPictureSizes();
        // Iterate through all available resolutions and choose one
        for (Camera.Size size : sizes) {
            Log.i("Resolution", "Available resolution: " + size.width + " " + size.height);
        }
        //set resolution at 320*240
        params.setPreviewSize(320,240);

        //set frame rate at 10 fps
        List<int[]> frameRates = params.getSupportedPreviewFpsRange();
        int last = frameRates.size() - 1;
        params.setPreviewFpsRange(10000, 10000);
        //set Image Format
        //params.setPreviewFormat(ImageFormat.NV21);
        mCamera.setParameters(params);


    } catch (IOException e) {
        e.printStackTrace();
    }


}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    //need to stop the preview and restart on orientation change
    if (mHolder.getSurface() == null) {
        return;
    }
    //stop preview
    mCamera.stopPreview();

    //start again
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    }


}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    //stop and release
    mCamera.startPreview();
    mCamera.release();
}

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

    int frameHeight = camera.getParameters().getPreviewSize().height;
    int frameWidth = camera.getParameters().getPreviewSize().width;
    // number of pixels//transforms NV21 pixel data into RGB pixels
    int rgb[] = new int[frameWidth * frameHeight];
    // convertion
    int[] myPixels = decodeYUV420SP(rgb, data, frameWidth, frameHeight);

    Log.d("myPixel", String.valueOf(myPixels.length));

}

//yuv decode
int[] decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {

    final int frameSize = width * height;
    int r, g, b, y1192, y, i, uvp, u, v;
    for (int j = 0, yp = 0; j < height; j++) {
        uvp = frameSize + (j >> 1) * width;
        u = 0;
        v = 0;
        for (i = 0; i < width; i++, yp++) {
            y = (0xff & ((int) yuv420sp[yp])) - 16;
            if (y < 0)
                y = 0;
            if ((i & 1) == 0) {
                // above answer is wrong at the following lines. just swap ***u*** and ***v***
                u = (0xff & yuv420sp[uvp++]) - 128;
                v = (0xff & yuv420sp[uvp++]) - 128;
            }

            y1192 = 1192 * y;
            r = (y1192 + 1634 * v);
            g = (y1192 - 833 * v - 400 * u);
            b = (y1192 + 2066 * u);

            r = Math.max(0, Math.min(r, 262143));
            g = Math.max(0, Math.min(g, 262143));
            b = Math.max(0, Math.min(b, 262143));

            // combine RGB
            rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) | 0xff);
        }
    }
return rgb;
}
}

这里的解码方法应该给出一个十六进制格式的 RGB 颜色空间(很确定它没问题,因为大多数答案都是相同的)。我面临的问题是,当我不太确定如何在 OnPreviewFrame 方法中调用它时,它会将 RGB 值分别显示到日志中。

NB 就像我说的,我见过很多类似的问题,但找不到解决方案。我不想存储文件(图像/视频),因为当我将相机指向某种颜色时,我只需要实时相机预览中的 RGB/YUV 值。

我需要 rgb 或 yuv 值,因为我想根据时间绘制图表。

任何帮助将不胜感激。

【问题讨论】:

  • 您没有在onPreviewFrame 方法中获得任何值?在你的日志里面?
  • 正是我的问题。我用我如何尝试在 onPreviewFrame 中获取值来更新问题。但据我了解, myPixels 将返回一个数组。我如何将它分成RGB?
  • 您确定您的设备支持 320x240 像素分辨率和 10 FPS 吗?即使是这样,logcat 也无法每秒打印 10 次 ~230K 整数。您可以按此速率打印一个像素的 RGB。
  • 是的,它确实支持分辨率和 fps。但我实际上并没有得到你所说的~230K整数的意思。以前我使用的是opencv,它确实正确打印出RGB值。但是,我无法控制fps和分辨率,因此我开始使用相机api .

标签: android image-processing colors camera


【解决方案1】:

如果问题是从 RGB 数组中获取 R、G 和 B 的单独值,请查看此 SO 帖子 here

希望对你有帮助!

【讨论】:

  • 我试图遵循这一点,但由于某种原因,如果我在 decode 或 onPreviewFrame 中记录一些内容,我在 logcat 上没有得到任何信息。
  • 你不会因为你的方法,decodeYUV 返回 void。因此你的像素数组是空的。 ` int[] myPixels = decodeYUV420SP(rgb, data, frameWidth, frameHeight);` 因此,尝试让 rgb[] 从方法返回,或使用 data[] 记录 RGB 值。
  • 我在发布这个问题后就这样做了。我将 void 更改为int[],最后添加了return rgb;。然后当我在onPreviewFrame 中添加int color = (int)Long.parseLong(myPixels, 16); int r = (color &gt;&gt; 16) &amp; 0xFF; int g = (color &gt;&gt; 8) &amp; 0xFF; int b = (color &gt;&gt; 0) &amp; 0xFF 时,它要求我添加String.valueOf。我也这样做了。但还是没用。
  • 好的。做一件事,记录数组值。喜欢 log myPixels.length 只是为了检查它是否不是 0
  • 我已经更新了代码。请您再看一遍,并告诉我我尝试登录 onPreviewFrame 的方式是否正确。我没有在日志中得到任何回报。还要再看一下解码方法。我为麻烦道歉。
猜你喜欢
  • 2017-01-25
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
  • 2013-08-10
  • 2012-07-04
  • 2019-09-02
  • 1970-01-01
相关资源
最近更新 更多