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

Java 如何从openCV android中的字节[]获取Mat对象?,java,android,opencv,image-processing,bitmap,Java,Android,Opencv,Image Processing,Bitmap,我正在Android中使用OpenCV库。我有一个类实现了PictureCallBack 覆盖方法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 aga

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

覆盖方法
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);
    }
}
因为我希望在图像处理中进一步使用图像数据,而不是保存和重新加载图像

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

  • 我不知道图像发生了什么

    Mat m=new Mat();
    m、 put(0,0,数据)

  • 转换为位图,然后使用
    bitmapToMat()
    在这种情况下,红色变为蓝色


  • 在保存图像以备将来使用时,我也没有遇到任何问题,但这导致了一个例外,因为当我使用以前存储的图像时,文件尚未生成。

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

    Mat mat = new Mat(width, height, CvType.CV_8UC3);
    mat.put(0, 0, data);
    
    确保您使用的垫子类型正确。可能您的数据不是3字节RGB格式,您应该使用其他类型,例如
    CvType.CV\u 8UC1


    祝你好运

    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() + ")");
    }
    
    如果红色和蓝色被交换,那么听起来好像onPictureTaken()中的字节数据是BGRA格式的。您可以使用以下方式将其交换为RGBA:

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

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

    最好、最简单的方法如下:

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

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

    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);
    
    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);
    
    }
    
    OpenCV侧(NDK)

        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);
    
    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);
    
    }
    

    您可以使用作为opencv一部分的imdecode方法(这是针对emgucv的,但在其他版本的opencv上应该有类似的操作,语法可能不同)

    例如:

    byte [] imageArray
    Mat dest
    
    CvInvoke.Imdecode(imageArray, ImreadModes.Unchanged, dest)
    

    你能定义数据吗??它是什么?
    数据
    字节[]
    数组,包含一系列正确格式的像素。它可以从例如
    buffereImage
    -
    byte[]data=((DataBufferByte)image.getRaster().getDataBuffer()).getData()获取高度和宽度参数是错误的。垫=新垫(高度、宽度CvType.CV_8UC3);我在很多类似的问题上都看到了这一点,但它导致了与内存相关的崩溃。当图像大于预期的Mat输出时,这似乎不是一个可行的解决方案。