所以,钻入问题后,我已经找到了问题的根源。
让我们来看看OpenCV JavaCameraView
类和它的CameraBridgeViewBase
基类。 问题在于,在onPreviewFrame
方法中收到的byte[]
数组中的相机帧被错误地解码。
的代码的确切地方,解码过程发生是Mat rgba()
法在内部JavaCameraFrame
类JavaCameraView
的实现:
public Mat rgba() {
Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
return mRgba;
}
正如我们看到的,Imgproc.cvtColor(...)方法用于将帧从YUV转换为RGBA。 NV21 YUV -> RGBA
转换发生在那里。在初始化过程中,我们将格式设置为NV21,所以这应该是正确的。此外,every Android device should support NV21。另外,我们可以检查设备是否接受使用调试器的格式为:
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()));
}
两个手机(HTC感觉)和模拟器报道为使用确实NV21。但是,如果我们将COLOR_YUV2RGBA_NV21
更改为COLOR_YUV2RGB_I420
(YV12和I420是相同的东西,只需将Y和V倒置;),我们将看到仿真器最终将获得适当的颜色空间。在params.setPreviewFormat(ImageFormat.NV21);
中将NV21更改为YV12我们会得到类似的结果。看起来像是在Imgproc.cvtColor或Android中有bug。
这是解决方案。 更改public Mat rgba()
方式如下:
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
是一个新的int
变量,它是这样声明:
private int previewFormat = ImageFormat.NV21;
添加以下更改初始化:
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();
...
}
重要:
请注意:这只是一个临时解决方案,以使OpenCV在我的情况下可以与仿真器一起使用。应该进一步研究。检查设备是否在onPreviewFrame中使用正确的图像格式很容易。当我有一些时间时,我会回到这个。
使用Android Studio 1.5.1并模拟API 23时,上述仅在''generic''被交换到'“android”'时才起作用。尽管如此,改变之后的工作仍然完美无瑕。 – 2016-01-26 19:55:20
我只是试过这个,它工作正常。虽然,我不确定这是否是首选的方法,或者应该以不同的方式修复。我在OpenCV存储库中创建了一个问题,如果接受它,可以将其作为请求提交。 – 2017-02-09 23:24:10
为了可追溯性:https://github.com/opencv/opencv/issues/8166 – 2017-02-14 01:26:16