web-dev-qa-db-ja.com

openCV androidでByte []からMatオブジェクトを取得する方法は?

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

画像を保存して再ロードする代わりに、画像データを画像処理でさらに使用したいので。

Byte配列からMatオブジェクトを取得する最も効率的な方法は何ですか?私はすでにこれらのアプローチを試しました:

  1. 画像に何が起こったのか分からない。

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

  2. ビットマップに変換してからbitmapToMat()を使用します。この場合、赤色が青色になります。

また、将来使用するために画像を保存しても問題はありませんが、以前に保存した画像を使用している場合、ファイルがまだ生成されていないため、例外が発生します。

13
Ankur Gautam

画像/マットの幅と高さ、チャネルの深さを指定する必要があります。

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

正しいタイプのマットを使用していることを確認してください。多分あなたのデータは3バイトのRGBフォーマットではなく、あなたは別のタイプを使うべきです。 CvType.CV_8UC1
幸運を!

18
lukk

最良かつ最も簡単な方法は次のとおりです。

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

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

形式は実際にはデバイス固有です-私が持っていた1つのデバイスでは、それはYUVとして渡されます。

1
timegalore

私にとって、次は私にとってうまくいきます:

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側(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);

}
0
Hpsaturn