2017-07-14 5 views
1

Nous développons une application sur Unity3D qui prendra l'image de l'écran et la transférera à Texture2D. Nous avons des difficultés avec les performances sur les appareils à faible consommation.
Le code est donné ci-dessous. Nous faisons une capture d'écran, puis nous lisons des pixels (ReadPixels) - ici le problème se pose, une application fonctionne terriblement lentement.RenderTexture to Texture2D est très lent

Nous avons essayé de prendre la texture de l'appareil photo, mais cela ne fonctionne pas parce que notre scanner fonctionne en parallèle avec Kudan, et à son tour, il bloque l'accès à la caméra. Ensuite, nous avons essayé de limiter la zone d'écran à scanner (en prenant pour scanner une petite fenêtre, mais pas en plein écran) - mais il n'y avait pas d'augmentation visible de la performance.
Quelqu'un peut-il m'aider?
Voici notre code:

IEnumerator DecodeScreen() 
{ 
    yield return new WaitForEndOfFrame(); 
    RenderTexture RT = new RenderTexture(Screen.width, Screen.height,24); 
    Texture2D screen = new Texture2D(RT.width, RT.height, TextureFormat.RGB24, false, false); 
    screen.ReadPixels(new Rect(0, 0, RT.width, RT.height), 0, 0); 
    screen.Apply(); 
    Debug.Log(resultText.text); 
    GetComponent().targetTexture = null; 
    Destroy(RT); 
} 

Répondre

1

Il y a quelques façons d'améliorer le code ou la manière facultative pour convertir RenderTexture à Texture2D.

.Déclarez WaitForEndOfFrame comme variable en dehors de la fonction afin de ne pas avoir à le faire chaque fois que cette fonction est appelée.

. Vous créez un nouveau Texture2D chaque fois que vous appelez cette fonction. Faites-le une fois dans la fonction Start puis réutilisez-le. Vous pouvez redimensionner librement la texture si les changements de largeur ou de hauteur sont RenderTexture.

. Vous créez également un nouveau RenderTexture chaque fois que vous appelez cette fonction. Il est plus rapide d'utiliser RenderTexture.GetTemporary pour obtenir temporaire RenderTexture. Lorsque vous avez terminé, vous pouvez RenderTexture.ReleaseTemporary pour le libérer.

Texture2D screen = null; 
WaitForEndOfFrame frameEndWait = new WaitForEndOfFrame(); 

void Start() 
{ 
    screen = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false, false); 
} 

IEnumerator DecodeScreen() 
{ 
    yield return frameEndWait; 
    RenderTexture RT = RenderTexture.GetTemporary(Screen.width, Screen.height, 24); 
    //Resize only when Texture2D is null or when its size changes 
    if (screen == null || screen.width != RT.width || screen.height != RT.height) 
    { 
     screen.Resize(RT.width, RT.height, TextureFormat.RGB24, false); 
     //screen = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false, false); 
    } 
    screen.ReadPixels(new Rect(0, 0, RT.width, RT.height), 0, 0); 
    screen.Apply(); 
    RenderTexture.ReleaseTemporary(RT); 
} 

Voici d'autres options que vous avez:

utiliser des plugins natifs avec C++:

Envoyer RenderTexture.GetNativeTexturePtr() à un côté natif de votre C++ puis créer une texture OpenGL à partir de cela et le charger de C# avec pointeur en utilisant la fonction Texture2D.CreateExternalTexture et continuez à le mettre à jour avec la fonction Texture2D.UpdateExternalTexture.


Le meilleur moyen de le faire est de abandonnerRenderTexture. Utilisez la fonction OpenGL glReadPixels pour prendre une capture d'écran à partir du côté C++ puis envoyez l'image à Unity avec un pointeur et chargez-la avec la fonction Texture2D.CreateExternalTexture et continuez à la mettre à jour avec la fonction Texture2D.UpdateExternalTexture. Vous pouvez modifier le code pixel de la souris à partir de mon other post et le faire faire.