本文介绍了OpenCV的Andr​​oid的 - 使用CameraBridgeViewBase颜色问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到使用Android模拟器和放大器奇怪的问题; OpenCV的 CameraBridgeViewBase

使用 onCameraFrame 我得到的照片,看起来像它不是去codeD正常。

 公共垫onCameraFrame(CvCameraViewFrame inputFrame){
    返回inputFrame.rgba();
}

使用'inputFrame.gray()我得到什么的预期 - 黑白图像没有任何瑕疵或其他问题

这就是我得到:

我试过到目前为止:


  1. 不同的API级别(从15到21)。

  2. 不同的模拟器:Genymotion&放大器;谷歌Android模拟器。

  3. 不同平台架构 - ARM和英特尔的x86

  4. 启动不同的笔记本电脑模拟器使用Linux:它的工作原理如预期,这个问题就没了

  5. 启动应用程序,使用OpenCV的,从Play商店下载。他们做的工作! 然而

    1. 启动应用程序,运行正确,然后将其关闭。

    2. 启动我的应用程序(或OpenCV的教程之一),然后将其关闭。

    3. 从再次启动5.1应用程序,我看到它受到同样的错误!


  6. OpenCV的不同版本(2.4.9和2.4.10)。

  7. 不同版本OpenCV的经理(一个从Play商店和2.4.9&安培; 2.4.10来自OpenCV的包)

  8. 从OpenCV的包装最后,正如我在5.2注意到,precompiled教程的apk文件是由问题的影响了。

一切正常对我真正的Andr​​oid设备。

在看的 CameraBridgeViewBase 和Java /原生相机类源后,我来到了同时解码图像出现问题的决定。也许有一些乱用特定平台的摄像头输出格式(YUV,NV21)。然而,奇怪的是.gray()给出了一个正确的图像(没有任何瑕疵)。

我使用的是Mac OS X的10.10优胜美地和MacBook Air用的Facetime HD相机如果该事项。

这是如何克服这个问题与放任何想法;在寻找问题的根源是帮助极大的AP preciated!


解决方案

所以,我已经找到了问题的根源钻入问题后。

让我们来看看在OpenCV的 JavaCameraView 类和 CameraBridgeViewBase 基类。
问题是,作为收到相机帧字节[] 阵列上previewFrame 方法是去codeD不正确。

code的确切地方,解码过程中发生的是垫RGBA的实现()在内方法 JavaCameraFrame 类的 JavaCameraView :

 公共垫RGBA(){
        Imgproc.cvtColor(mYuvFrameData,mRgba,Imgproc.COLOR_YUV2RGBA_NV21,4);
        返回mRgba;
    }

正如我们看到的,Imgproc.cvtColor(...)方法,以便从框架YUV转换为RGBA使用。 NV21 YUV - > RGBA 转换发生在那里。在初始化过程中,我们将格式设置为NV21,所以这应该是正确的。此外,。另外,我们可以通过检查调试设备是否接受的格式为:

 保护布尔initializeCamera(INT宽度,高度INT){
    ...
    params.set previewFormat(ImageFormat.NV21);
    ...
    mCamera.setParameters(PARAMS);
    ...
    PARAMS = mCamera.getParameters();
    Log.d(TAG,的String.format(实际preVIEW格式为0x%X,params.get previewFormat()));
}

这两个手机(HTC感觉)和模拟器报道中的确使用NV21。

不过,如果我们改变 COLOR_YUV2RGBA_NV21 COLOR_YUV2RGB_I420 (YV12和I420是一样的东西,只是Y和V反转;),我们会看到,仿真器将得到适当的色彩空间最后。在 params.set previewFormat(ImageFormat.NV21)更改为NV21 YV12; 我们将得到类似的结果。貌似有缺陷无论是在Imgproc.cvtColor或Android系统。

这里谈到的解决方案。
更改公共垫RGBA()通过以下方式:

 公共垫RGBA(){
        如果(previewFormat == ImageFormat.NV21){
            Imgproc.cvtColor(mYuvFrameData,mRgba,Imgproc.COLOR_YUV2RGBA_NV21,4);
        }
        否则,如果(previewFormat == ImageFormat.YV12){
            Imgproc.cvtColor(mYuvFrameData,mRgba,Imgproc.COLOR_YUV2RGB_I420,4); // COLOR_YUV2RGBA_YV12产生反色
        }
        返回mRgba;
    }

previewFormat 是一个新的 INT 变量,它的声明是这样的:

 私人诠释previewFormat = ImageFormat.NV21;

添加以下更改初始化:

 保护布尔initializeCamera(INT宽度,高度INT){
        ...
                params.set previewFormat(ImageFormat.NV21);
                //通用= Android模拟器
                如果(Build.BRAND.equalsIgnoreCase(通用)){
                    params.set previewFormat(ImageFormat.YV12);
                }
                ...
                mCamera.setParameters(PARAMS);
                PARAMS = mCamera.getParameters();
                previewFormat = params.get previewFormat();
        ...
}

重要:结果
请注意:这是为了使OpenCV的有用,在我的情况下,仿真器只是一个临时解决方案。进一步的研究应该做的。这是很容易检查设备是否在使用正确的图像格式在previewFrame。我会回到这个时候我有一段时间了。

I'm encountering strange problem using Android emulators & OpenCV CameraBridgeViewBase.

Using onCameraFrame I get a picture that looks like it wasn't decoded properly.

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    return inputFrame.rgba();
}

Using 'inputFrame.gray()' I get what's expected - black and white image without artifacts or any other issues.

That's what I get:

One more picture (bigger one)

What I've tried so far:

  1. Different API levels (from 15 up to 21).
  2. Different emulators: Genymotion & Google Android emulator.
  3. Different platform architectures - both ARM and Intel x86.
  4. Launching emulator on different laptop with Linux: it works as expected, the issue is gone!
  5. Launching apps, using OpenCV, downloaded from Play Store. They DO work! However

    1. Launch app that works right, then close it.
    2. Launch my app (or one of the OpenCV tutorials), then close it.
    3. Launching app from the 5.1 again I see that it's affected by the same bug!

  6. Different OpenCV versions (2.4.9 and 2.4.10).
  7. Different versions of the OpenCV manager (one from the Play Store and 2.4.9 & 2.4.10 from OpenCV package).
  8. Finally, as I noticed in 5.2, precompiled tutorial .apk files from the OpenCV package are affected by the issue too.

Everything works as expected on my real android devices.

After looking at sources of the CameraBridgeViewBase and Java/Native camera classes I came to the decision that the problem occurs while decoding image. Probably there is some mess with platform-specific camera output format (YUV, NV21). However, it's strange that .gray() gives out a proper image (without artifacts).

I'm using Mac OS X 10.10 Yosemite and MacBook Air with "Facetime HD" camera if that matters.

Any ideas on how to overcome this problem & help in finding the root of the problem are greatly appreciated!

解决方案

So, after drilling into the problem I've found the root of the issue.

Let's take a look at the OpenCV JavaCameraView class and its CameraBridgeViewBase base class.The problem was that camera frames received as byte[] array in onPreviewFrame method were decoded incorrectly.

The exact place of code where the decoding process takes place is an implementation of the Mat rgba() method in inner JavaCameraFrame class of the JavaCameraView:

    public Mat rgba() {
        Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
        return mRgba;
    }

As we see, Imgproc.cvtColor(...) method is used in order to convert frame from YUV to RGBA. NV21 YUV -> RGBA conversion takes place there. During the initialization process we set the format to NV21, so this should be right. Moreover, every Android device should support NV21. Also, we can check whether device accepted the format using debugger:

protected boolean initializeCamera(int width, int height) {
    ...
    params.setPreviewFormat(ImageFormat.NV21);
    ...
    mCamera.setParameters(params);
    ...
    params = mCamera.getParameters();
    Log.d(TAG, String.format("Actual preview format is 0x%X", params.getPreviewFormat()));
}

Both phone (HTC Sensation) and emulator reported to be using NV21 indeed.

However, if we change COLOR_YUV2RGBA_NV21 to COLOR_YUV2RGB_I420 (YV12 and I420 is the same thing, just with Y and V inverted;) we'll see that emulator will get a proper color space finally. Changing NV21 to YV12 in params.setPreviewFormat(ImageFormat.NV21); we'll get similar results. Looks like there's bug either in Imgproc.cvtColor, or in Android.

Here comes the solution.Change public Mat rgba() the following way:

    public Mat rgba() {
        if (previewFormat == ImageFormat.NV21) {
            Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
        }
        else if (previewFormat == ImageFormat.YV12) {
            Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_I420, 4);  // COLOR_YUV2RGBA_YV12 produces inverted colors
        }
        return mRgba;
    }

previewFormat is a new int variable, it's declared this way:

private int previewFormat = ImageFormat.NV21;

Add following changes to the initialization:

protected boolean initializeCamera(int width, int height) {
        ...
                params.setPreviewFormat(ImageFormat.NV21);
                // "generic" = android emulator
                if (Build.BRAND.equalsIgnoreCase("generic")) {
                    params.setPreviewFormat(ImageFormat.YV12);
                }
                ...
                mCamera.setParameters(params);
                params = mCamera.getParameters();
                previewFormat = params.getPreviewFormat();
        ...
}

Important:
Please note: this is just a temporary solution in order to make OpenCV usable with emulator in my case. Further research should be done. It's quite easy to check whether device uses correct image format in onPreviewFrame. I'll get back to this when I have some time.

这篇关于OpenCV的Andr​​oid的 - 使用CameraBridgeViewBase颜色问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 10:38