web-dev-qa-db-fra.com

Comment obtenir l'objet Mat à partir du Byte [] dans openCV android?

Je travaille avec la bibliothèque OpenCV sous Android. J'ai une classe qui implémente PictureCallBack.

La méthode de substitution onPictureTaken() est donnée ci-dessous,

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

Comme je veux que les données d’image soient utilisées plus avant dans le traitement d’image au lieu de sauvegarder et de recharger l’image.

Quel est le moyen le plus efficace d’obtenir l’objet Mat du tableau Byte? J'ai déjà essayé ces approches:

  1. Je ne sais pas ce qui est arrivé à l'image.

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

  2. La conversion en bitmap utilise ensuite bitmapToMat(). Dans ce cas, la couleur rouge devient bleue.

Je n'ai également aucun problème pour enregistrer l'image pour une utilisation ultérieure, mais cela me conduit à une exception, car le fichier n'a pas encore été généré, lorsque j'utilise l'image précédemment enregistrée.

11
Ankur Gautam

Vous devez spécifier la largeur et la hauteur de l'image/Mat et la profondeur des canaux.

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

Assurez-vous que vous utilisez le bon type de tapis. Peut-être que vos données ne sont pas au format RVB sur 3 octets et que vous devriez utiliser un autre type, par exemple CvType.CV_8UC1.
Bonne chance!

16
lukk

Le meilleur et le plus simple est comme ça:

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

opencv a un moyen élégant d’écrire Mats dans des fichiers - il peut générer différents formats en fonction de l’extension de fichier fournie. Voici un exemple minimal:

    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() + ")");
}

si les couleurs rouge et bleu sont permutées, il semble que vos données d'octet de onPictureTaken () soient au format BGRA. Vous pouvez l'échanger contre RGBA en utilisant:

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

le format est en fait spécifique à un appareil - sur un appareil que j'ai eu, il devient YUV.

1
timegalore

Pour moi, la prochaine marche bien pour moi:

Côté 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);

Côté 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