Convert OpenCV Mat to Texture2D?

Metacontext:

I am currently working on a game that uses opencv as a replacement for conventional inputs (keyboard, mouse, etc.). I am using Unity3D C # and opencv scripts in C ++ through DllImports. My goal is to create an image inside my game coming from opencv.

Code Context:

As usual in OpenCV, I use Mat to represent my image. This is how I export image bytes:

cv::Mat _currentFrame;

...

extern "C" byte * EXPORT GetRawImage()
{
    return _currentFrame.data;
}

And here is how I import from C #:

[DllImport ("ImageInputInterface")]
private static extern IntPtr GetRawImage ();

...

public static void GetRawImageBytes (ref byte[] result, int arrayLength) {
    IntPtr a = GetRawImage ();
    Marshal.Copy(a, result, 0, arrayLength);
    FreeBuffer(a);
}

Judging by how I understand OpenCV, I expect the byte array to be structured this way when serialized in the uchar pointer:

b1, g1, r1, b2, g2, r2, ...

I convert this BGR array to an RGB array using:

public static void BGR2RGB(ref byte[] buffer) {
    byte swap;
    for (int i = 0; i < buffer.Length; i = i + 3) {
        swap = buffer[i];
        buffer[i] = buffer[i + 2];
        buffer[i + 2] = swap;
    }
}

Finally, I use Unity LoadRawTextureDatato load bytes into the texture:

this.tex = new Texture2D(
    ImageInputInterface.GetImageWidth(),
    ImageInputInterface.GetImageHeight(),
    TextureFormat.RGB24,
    false
);

...

ImageInputInterface.GetRawImageBytes(ref ret, ret.Length);
ImageInputInterface.BGR2RGB(ref ret);
tex.LoadRawTextureData(ret);
tex.Apply();

Results:

, , - , , , , . :

[, ]

ojumW.png

, , , , RGB, :

[ ]

bN1Y4.png

[ ]

AA32z.png

[ ]

Wmkjr.png

:

[Spooky Lines]

ckEBM.png

:

[ ]

6TyR1.png

:

, OpenCV? , , Unity LoadRawTextureData, - ?

OpenCV Mat.data?

UPDATE

@Programmer .

[ ]

FqXbCaU.png

script, - . BGR2RGBA, RGB2RGBA:

extern "C" void EXPORT GetRawImage( byte *data, int width, int height )
{
    cv::Mat resizedMat( height, width, _currentFrame.type() );
    cv::resize( _currentFrame, resizedMat, resizedMat.size(), cv::INTER_CUBIC );

    cv::Mat argbImg;
    cv::cvtColor( resizedMat, argbImg, CV_BGR2RGBA );
    std::memcpy( data, argbImg.data, argbImg.total() * argbImg.elemSize() );
}
+4
1

SetPixels32 LoadRawTextureData. , ++, #. Color32 # GCHandle.Alloc, Color32 ++, cv::resize cv::Mat , #. .

, cv::Mat RGB ARGB, std::memcpy ++. SetPixels32 Color32 Texture2D. , - . , .

++:

cv::Mat _currentFrame;

void GetRawImageBytes(unsigned char* data, int width, int height)
{
   //Resize Mat to match the array passed to it from C#
    cv::Mat resizedMat(height, width, _currentFrame.type());
    cv::resize(_currentFrame, resizedMat, resizedMat.size(), cv::INTER_CUBIC);

    //You may not need this line. Depends on what you are doing
    cv::imshow("Nicolas", resizedMat);

    //Convert from RGB to ARGB 
    cv::Mat argb_img;
    cv::cvtColor(resizedMat, argb_img, CV_RGB2BGRA);
    std::vector<cv::Mat> bgra;
    cv::split(argb_img, bgra);
    std::swap(bgra[0], bgra[3]);
    std::swap(bgra[1], bgra[2]);
    std::memcpy(data, argb_img.data, argb_img.total() * argb_img.elemSize());
}

#

GameObject Renderer, , cv::Mat . , :

using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class Test : MonoBehaviour
{
    [DllImport("ImageInputInterface")]
    private static extern void GetRawImageBytes(IntPtr data, int width, int height);

    private Texture2D tex;
    private Color32[] pixel32;

    private GCHandle pixelHandle;
    private IntPtr pixelPtr;

    void Start()
    {
        InitTexture();
        gameObject.GetComponent<Renderer>().material.mainTexture = tex;
    }


    void Update()
    {
        MatToTexture2D();
    }


    void InitTexture()
    {
        tex = new Texture2D(512, 512, TextureFormat.ARGB32, false);
        pixel32 = tex.GetPixels32();
        //Pin pixel32 array
        pixelHandle = GCHandle.Alloc(pixel32, GCHandleType.Pinned);
        //Get the pinned address
        pixelPtr = pixelHandle.AddrOfPinnedObject();
    }

    void MatToTexture2D()
    {
        //Convert Mat to Texture2D
        GetRawImageBytes(pixelPtr, tex.width, tex.height);
        //Update the Texture2D with array updated in C++
        tex.SetPixels32(pixel32);
        tex.Apply();
    }

    void OnApplicationQuit()
    {
        //Free handle
        pixelHandle.Free();
    }
}
+4

Source: https://habr.com/ru/post/1695319/


All Articles