Java 如何从openCV android中的Byte[]获取Mat对象?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21113190/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:40:12  来源:igfitidea点击:

How to get the Mat object from the Byte[] in openCV android?

javaandroidopencvimage-processingbitmap

提问by Ankur Gautam

I am working with OpenCV library in Android. I have a class which implements PictureCallBack.

我正在 Android 中使用 OpenCV 库。我有一个实现PictureCallBack.

The override method onPictureTaken()is as given below,

覆盖方法onPictureTaken()如下所示,

     @Override
public void onPictureTaken(byte[] data, Camera camera) {
    Log.i(TAG, "Saving a bitmap to file");
    // The camera preview was automatically stopped. Start it again.
    mCamera.startPreview();
    mCamera.setPreviewCallback(this);

    // Write the image in a file (in jpeg format)
    try {
        FileOutputStream fos = new FileOutputStream(mPictureFileName);
        fos.write(data);
        fos.close();

    } catch (java.io.IOException e) {
        Log.e("PictureDemo", "Exception in photoCallback", e);
    }
}

As I want image data to be used further in image processing in stead of saving and reloading the image.

因为我希望在图像处理中进一步使用图像数据,而不是保存和重新加载图像。

What is the most efficient way for getting the Mat object from the Byte array? I have already tried these approaches:

从 Byte 数组中获取 Mat 对象的最有效方法是什么?我已经尝试过这些方法:

  1. Don't know what happened to the image.

    Mat m=new Mat(); m.put(0,0,data);

  2. Converting to Bitmap then use bitmapToMat()In this case , red color becomes blue .

  1. 不知道图片怎么了。

    Mat m=new Mat(); m.put(0,0,data);

  2. 转换为 Bitmap 然后使用bitmapToMat()在这种情况下,红色变为蓝色。

I also don't have any problem in saving the image for future use,but this leads me an exception because the file not have been generated yet, when I am using the previously stored image.

我在保存图像以备将来使用时也没有任何问题,但这导致我出现异常,因为当我使用以前存储的图像时,文件尚未生成。

采纳答案by lukk

You have to specify width and height of the image/Mat and channels depth.

您必须指定图像/Mat 的宽度和高度以及通道深度。

Mat mat = new Mat(width, height, CvType.CV_8UC3);
mat.put(0, 0, data);

Make sure you are using correct type of Mat. Maybe your data is not in 3 bytes RGB format and you should use another type e.g. CvType.CV_8UC1.
Good luck!

确保您使用正确类型的垫子。也许您的数据不是 3 字节 RGB 格式,您应该使用另一种类型,例如CvType.CV_8UC1.
祝你好运!

回答by timegalore

opencv has a neat way to writing Mats to files - it can generate different formats based on the file extension provided. Here is a minimal example:

opencv 有一种将 Mats 写入文件的巧妙方法 - 它可以根据提供的文件扩展名生成不同的格式。这是一个最小的例子:

    public void writeImageToFile(Mat image, String filename) {

    File root = Environment.getExternalStorageDirectory();
    File file = new File(root, filename);

    Highgui.imwrite(file.getAbsolutePath(), image);

    if (DEBUG)
        Log.d(TAG,
                "writing: " + file.getAbsolutePath() + " (" + image.width()
                        + ", " + image.height() + ")");
}

if red and blue is swapped then it sounds like your byte data from onPictureTaken() is in BGRA format. You can swap it to RGBA using:

如果交换了红色和蓝色,那么听起来您来自 onPictureTaken() 的字节数据是 BGRA 格式。您可以使用以下方法将其交换为 RGBA:

Imgproc.cvtColor(bgrImg, rgbImg, Imgproc.COLOR_BGR2RGB);

the format is actually device specific - on one device I had it comes through as YUV.

该格式实际上是特定于设备的 - 在我的一台设备上,它以 YUV 的形式出现。

回答by Bahramdun Adil

The best and easiest way is like this:

最好和最简单的方法是这样的:

byte[] bytes = FileUtils.readFileToByteArray(new File("aaa.jpg"));
Mat mat = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);

回答by Hpsaturn

For me, the next works fine for me:

对我来说,下一个对我来说很好:

Java side:

Java方面

    Bitmap bitmap = mTextureView.getBitmap(mWidth, mHeight);
    int[] argb = new int[mWidth * mHeight];
    // get ARGB pixels and then proccess it with 8UC4 OpenCV convertion
    bitmap.getPixels(argb, 0, mWidth, 0, 0, mWidth, mHeight);
    // native method (NDK or CMake)
    processFrame8UC4(argb, mWidth, mHeight);

OpenCV side (NDK):

OpenCV 端(NDK)

JNIEXPORT jint JNICALL com_native_detector_Utils_processFrame8UC4
    (JNIEnv *env, jobject object, jint width, jint height, jintArray frame) {

    jint *pFrameData = env->GetIntArrayElements(frame, 0);
    // it is the line:
    Mat mFrame = Mat(height,width,CV_8UC4,pFrameData).clone();
    // your code..
    env->ReleaseIntArrayElements(frame, pFrameData, 0);

}