Преобразование Texture2D в Byte [] с помощью EncodeToJPG (в OpenVR)

У меня есть один вопрос!

Я просто хочу, просто ... преобразовать Texture2D в Byte [] с помощью функции EncodeToJPG ()!

Моя рабочая область - Unity и C # Script, + OpenCvSharp.

Может быть, вы думаете, что это легко, но у него есть проблемы.

этот скрипт использует OpenVR (HTC VIVE).

Во всяком случае, вот мой источник.

var source = SteamVR_TrackedCamera.Source(undistorted);

//Receive texture data from VR.
texture = source.texture;

//Debug.Log(source.texture.width + "/" + source.texture.height);    
//size : 612 /460
if (texture == null)
{
    return;
}

//Input texture data into material, and it's in unity (quad GameObject).
//this G.O print display like camera
material.mainTexture = texture;


//here is my src, I want to save Image but texture.EncodeToJPG has some error.
Cv2.ImShow("_Texture ...", Mat.FromImageData(texture.EncodeToJPG()));
Cv2.ImWrite(SavePath+ "Image.jpg", Mat.FromImageData(texture.EncodeToJPG()));

и ... есть проблема. переменная текстура имеет ненормальный тип Texture2D.

if (_texture == null)
{
    _texture = Texture2D.CreateExternalTexture((int)header.nWidth, (int)header.nHeight, TextureFormat.RGBA32, false, false, nativeTex);
    //_texture = new Texture2D(612, 460, TextureFormat.RGBA32, false);

    uint width = 0, height = 0;
    var frameBounds = new VRTextureBounds_t();
    if (trackedCamera.GetVideoStreamTextureSize(deviceIndex, frameType, ref frameBounds, ref width, ref height) == EVRTrackedCameraError.None)
    {
        // Account for textures being upside-down in Unity.
        frameBounds.vMin = 1.0f - frameBounds.vMin;
        frameBounds.vMax = 1.0f - frameBounds.vMax;
        this.frameBounds = frameBounds;
    }
}
else
{
    _texture.UpdateExternalTexture(nativeTex);
    //_texture.Apply();
}

эта _texture создается функцией CreateExternalTexture и имеет параметр типа Intptr с именем nativeTex.

Я не знаю, как мне это сделать?

+++ редактировать! Отображение ошибки +++

введите здесь описание изображения


person bolero    schedule 25.07.2018    source источник
comment
Вы сказали, что есть проблема, но не упомянули об этом. Что-то не так с EncodeToJPG?   -  person Programmer    schedule 25.07.2018
comment
Спасибо что сказал мне! хахаха   -  person bolero    schedule 25.07.2018
comment
да я знаю и у меня получилось. но у него такая же проблема.   -  person bolero    schedule 25.07.2018
comment
Какая у вас версия Unity и возникает ли эта проблема в редакторе? Также вызовите byte []img = texture.EncodeToJPG(), затем закомментируйте Mat.FromImageData код и сообщите мне результат   -  person Programmer    schedule 25.07.2018
comment
Моя версия Unity - 2018.02 v   -  person bolero    schedule 25.07.2018
comment
и в скрипте ошибки нет, но Cv2.ImShow (~) не работает, и этот источник: byte [] img = texture.EncodeToJPG (); Cv2.ImShow (_Texture .. ., Mat.FromImageData (img)); также имеют ту же проблему. (Не удалось получить ссылку на изображение.   -  person bolero    schedule 25.07.2018
comment
Вы получаете ошибку с byte[] img = texture.EncodeToJPG()? Если нет, то проблема не в EncodeToJPG. Кроме того, эта проблема возникает в редакторе?   -  person Programmer    schedule 25.07.2018
comment
У меня есть уверенность. Здесь произошла ошибка в texture.EncodeToJPG (), потому что текстура не является нормальным типом Texture2D, это может быть ... похоже на указатель? потому что эта текстура сделана с использованием параметра Intptr (nativeTex) (функция CreateExternalTexture)   -  person bolero    schedule 25.07.2018


Ответы (2)


Поскольку Unity может не иметь прямого доступа к внешней текстуре, я бы предложил сделать Graphics.Blit (), чтобы сначала передать эту текстуру в RenderTexture через графический процессор.

После того, как у вас есть текстура в RenderTexture, вам нужно перепрыгнуть через еще один обруч и прочитать пиксели из RenderTexture.active в другой стандарт, основанный на RAM, Texture2D, и тогда вы сможете его кодировать.

Не забудьте применить () текстуру после выполнения ReadPixels ()

person zambari    schedule 25.07.2018
comment
Спасибо! Я использовал функцию Graphics.Blit (), и это сработало! - person bolero; 30.07.2018
comment
@ipsuck хотя бы поблагодарить zambari за помощь. Вы даже не проголосовали за его ответ и не признали его в своем самопровозглашенном ответе - person mr5; 30.07.2018

объявил эту функцию:

private Texture2D ReadExternalTexture(Texture externalTexture)
{
    Texture2D myTexture2D = new Texture2D(texture.width, texture.height);
    //myTexture2D => empty Texture2D type variable
    if (myTexture2D == null)
    {
        Debug.Log("var: myTexture2D is null state.");
        myTexture2D = new Texture2D(texture.width, texture.height);
    }

    //Make RenderTexture type variable
    RenderTexture tmp = RenderTexture.GetTemporary(
    externalTexture.width,
    externalTexture.height,
    0,
    RenderTextureFormat.ARGB32,
    RenderTextureReadWrite.sRGB);

    Graphics.Blit(externalTexture, tmp);
    RenderTexture previous = RenderTexture.active;
    RenderTexture.active = tmp;

    myTexture2D.ReadPixels(new UnityEngine.Rect(0, 0, tmp.width, tmp.height), 0,     0);
    myTexture2D.Apply();

    RenderTexture.active = previous;
    RenderTexture.ReleaseTemporary(tmp);

    return myTexture2D;
}

и используйте функцию ReadExternalTexture в void Update ():

_texture = ReadExternalTexture(material.mainTexture);

Mat mat = Mat.FromImageData(_texture.EncodeToPNG());

Cv2.Flip(mat, mat, 0);
//Flip(src, dest, 0->updown flip / 1->leftright flip)

Cv2.Resize(mat, mat, new Size(224, 224));

Cv2.ImShow("Image", mat);
//Cv2.ImWrite(SavePath + "Image.jpg", mat);

и это сработало полностью!

person bolero    schedule 30.07.2018