Conversion de données YUV de caméra en ARGB avec renderscript

Ceci est ma première question ici dans stackoverflow.

Mon problème est: j'ai configuré une caméra dans Android et je reçois les données d'aperçu en utilisant un onPreviewFrame-listenener qui me transmet un tableau byte [] contenant les données d'image au format YUV Android par défaut (le périphérique ne prend pas en charge R5G6B5- format). Chaque pixel se compose de 12 bits qui rend la chose un peu délicate. Maintenant, ce que je veux faire, c'est de convertir les données YUV en données ARGB afin de faire un traitement d'image avec elle. Cela doit être fait avec renderscript, afin de maintenir une performance élevée.

  • Déterminer l'angle de vue de l'appareil photo du smartphone
  • Les événements d'analyse Firebase ne montrent pas de valeur
  • Comment désactiver l'action "tirer pour rafraîchir" et utiliser un seul indicateur?
  • Obtenir TypeNotPresentException suivi de ClassNotFoundException ou NoClassDefFoundError sur toutes les versions d'Android, à l'exception de Android
  • Comment puis-je afficher un cercle d'activité à thème holo?
  • Android - Détecter la fin de la presse longue
  • Mon idée était de passer deux pixels dans un élément (ce qui serait 24bits = 3 octets), puis retourner deux pixels ARGB. Le problème est que, dans Renderscript, un u8_3 (un vecteur 3dbit de 8 bits) est stocké en 32 bits, ce qui signifie que les 8 derniers bits sont inutilisés. Mais lorsque vous copiez les données d'image dans l'allocation, tous les 32 bits sont utilisés, de sorte que les 8 derniers bits se perdent. Même si j'ai utilisé une donnée d'entrée de 32 bits, les 8 bits restants sont inutiles, car ils ne représentent que 2/3 de pixel. Lors de la définition d'un élément constitué d'un réseau à 3 octets, il a effectivement une taille réelle de 3 octets. Mais alors, la méthode Allocation.copyFrom () – ne remplit pas l'affectation intégrée avec les données, arguant qu'il n'a pas le type de données approprié à remplir avec un octet [].

    La documentation renderscript indique qu'il existe un scriptIntrinsicYuvToRGB qui devrait faire exactement cela dans l'API de niveau 17. Mais en fait, la classe n'existe pas. J'ai téléchargé l'API niveau 17 même s'il semble ne plus pouvoir être téléchargeable. Quelqu'un at-il des informations à ce sujet? Est-ce que quelqu'un a déjà essayé un ScriptIntrinsic?

    Donc, en conclusion, ma question est: comment convertir les données de la caméra en données ARGB rapidement, hardwareaccelerated?

    Voilà comment le faire dans Dalvik VM (trouvé le code quelque part en ligne, ça fonctionne):

    @SuppressWarnings("unused") private void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); } } } 

  • Android Mediarecorder enregistre la durée de la vidéo différente de la durée attendue
  • Réactivation de l'appel d'appel de flacon dans Android avec rétrofit
  • ExpandableListView - Est-ce que l'expansion conditionnelle est possible?
  • Emulateur Android: impossible d'extraire la sélection
  • L'utilisation de Proguard pour Android dans Eclipse a eu une erreur
  • Le service de reconnaissance vocale Android est-il occupé?
  • 3 Solutions collect form web for “Conversion de données YUV de caméra en ARGB avec renderscript”

    Je suis sûr que vous trouverez l'application de test LivePreview intéressante … Cela fait partie du code source Android dans la dernière Jelly Bean (MR1). Il implémente un aperçu de caméra et utilise ScriptIntrinsicYuvToRgb pour convertir les données d'aperçu avec Renderscript. Vous pouvez parcourir la source en ligne ici:

    LivePreview

    Je n'ai pas pu exécuter ScriptInstrinsicYuvToRgb, alors j'ai décidé d'écrire ma propre solution RS.

    Voici le script prêt (nommé yuv.rs ):

     #pragma version(1) #pragma rs java_package_name(com.package.name) rs_allocation gIn; int width; int height; int frameSize; void yuvToRgb(const uchar *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) { uchar yp = rsGetElementAtYuv_uchar_Y(gIn, x, y) & 0xFF; int index = frameSize + (x & (~1)) + (( y>>1) * width ); int v = (int)( rsGetElementAt_uchar(gIn, index) & 0xFF ) -128; int u = (int)( rsGetElementAt_uchar(gIn, index+1) & 0xFF ) -128; int r = (int) (1.164f * yp + 1.596f * v ); int g = (int) (1.164f * yp - 0.813f * v - 0.391f * u); int b = (int) (1.164f * yp + 2.018f * u ); r = r>255? 255 : r<0 ? 0 : r; g = g>255? 255 : g<0 ? 0 : g; b = b>255? 255 : b<0 ? 0 : b; uchar4 res4; res4.r = (uchar)r; res4.g = (uchar)g; res4.b = (uchar)b; res4.a = 0xFF; *v_out = res4; } 

    N'oubliez pas de définir le format de prévisualisation de l'appareil photo sur NV21:

     Parameters cameraParameters = camera.getParameters(); cameraParameters.setPreviewFormat(ImageFormat.NV21); // Other camera init stuff: preview size, framerate, etc. camera.setParameters(cameraParameters); 

    Initialisation des allocations et utilisation du script:

     // Somewhere in initialization section // w and h are variables for selected camera preview size rs = RenderScript.create(this); Type.Builder tbIn = new Type.Builder(rs, Element.U8(rs)); tbIn.setX(w); tbIn.setY(h); tbIn.setYuvFormat(ImageFormat.NV21); Type.Builder tbOut = new Type.Builder(rs, Element.RGBA_8888(rs)); tbOut.setX(w); tbOut.setY(h); inData = Allocation.createTyped(rs, tbIn.create(), Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT & Allocation.USAGE_SHARED); outData = Allocation.createTyped(rs, tbOut.create(), Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT & Allocation.USAGE_SHARED); outputBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); yuvScript = new ScriptC_yuv(rs); yuvScript.set_gIn(inData); yuvScript.set_width(w); yuvScript.set_height(h); yuvScript.set_frameSize(previewSize); //..... 

    Méthode de rappel de l'appareil photo:

     public void onPreviewFrame(byte[] data, Camera camera) { // In your camera callback, data inData.copyFrom(data); yuvScript.forEach_yuvToRgb(inData, outData); outData.copyTo(outputBitmap); // draw your bitmap where you want to // ..... } 

    Pour ceux qui ne savaient pas, RenderScript est maintenant dans la bibliothèque de support Android, y compris l'intrinsèque.

    http://android-developers.blogspot.com.au/2013/09/renderscript-in-android-support-library.html

    http://android-developers.blogspot.com.au/2013/08/renderscript-intrinsics.html

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.