2017-04-24 2 views
1

J'ai une image YUV_420_888 provenant de l'appareil photo. Je veux recadrer un rectangle en niveaux de gris de cette image pour alimenter un algorithme de traitement d'image. Voilà ce que j'ai jusqu'à présent:Découper un rectangle en dehors de Camera2 Image

public static byte[] YUV_420_888toCroppedY(Image image, Rect cropRect) { 
    byte[] yData; 

    ByteBuffer yBuffer = image.getPlanes()[0].getBuffer(); 

    int ySize = yBuffer.remaining(); 

    yData = new byte[ySize]; 

    yBuffer.get(yData, 0, ySize); 

    if (cropRect != null) { 

     int cropArea = (cropRect.right - cropRect.left) * (cropRect.bottom - cropRect.top); 

     byte[] croppedY = new byte[cropArea]; 

     int cropIndex = 0; 

     // from the top of the rectangle, to the bottom, sequentially add rows to the output array, croppedY 
     for (int y = cropRect.top; y < cropRect.top + cropRect.height(); y++) { 

      // (2x+W) * y + x 
      int rowStart = (2*cropRect.left + cropRect.width()) * y + cropRect.left; 

      // (2x+W) * y + x + W 
      int rowEnd = (2*cropRect.left + cropRect.width()) * y + cropRect.left + cropRect.width(); 

      for (int x = rowStart; x < rowEnd; x++) { 
       croppedY[cropIndex] = yData[x]; 
       cropIndex++; 
      } 
     } 

     return croppedY; 
    } 

    return yData; 
} 

Cette fonction fonctionne sans erreur, mais l'image que je sors de c'est des ordures - il ressemble à ceci:

enter image description here

Je ne suis pas sûr comment résoudre ce problème ou ce que je fais mal.

+2

Je pense que vous devriez afficher l'image originale –

+0

@YandryPozo Je ne l'ai pas, je regardais à travers mon écran d'aperçu et il ne ressemble pas à ce – Carpetfizz

+1

Vous pourriez trouver la réponse en lisant sur les tampons gralloc et android: https://source.android.com/devices/graphics/arch-bq-gralloc. Ceci est un bon aperçu qui explique aussi pourquoi la largeur du tampon en octets peut différer de la largeur de l'image en pixels: https://www.codeproject.com/articles/991640/androids-graphics-buffer-management-system -part-je – l85m

Répondre

1

Vos calculs rowStart/end sont incorrects.

Vous devez calculer l'emplacement de début de ligne en fonction des dimensions de l'image source, et non des dimensions de la fenêtre de recadrage. Et je ne suis pas sûr d'où vous obtenez le facteur 2; il y a 1 octet par pixel dans le canal Y de l'image.

Ils devraient être à peu près:

int yRowStride = image.getPlanes()[0].getRowStride(); 
.. 
int rowStart = y * yRowStride + cropRect.left(); 
int rowEnd = y * yRowStride + cropRect.left() + cropRect.width();