Android decodeYUV420SP leads to green images?

Ok, so my question is pretty much identical to this: Convert preview frame to bitmap

However, his answer is not good, and trying to use it does not solve my problem.

What I'm trying to do at the moment is to send each frame as a bitmap to a method to determine if there are any faces, but first I need to create a bitmap, which means I have to use the decodeYUV420sp method, which doesn't seem to be working properly, and all of my images just come out as a green and yellow tie looking image. Here is my code:

This is from onPreviewFrame:

Parameters parameters = cam.getParameters(); Integer width = parameters.getPreviewSize().width; Integer height = parameters.getPreviewSize().height; Log.i("preview size: ", String.valueOf(width) + "x" + String.valueOf(height)); int[] mIntArray = new int[width*height]; // Decode Yuv data to integer array decodeYUV420SP(mIntArray, data, width, height); //Initialize the bitmap, with the replaced color Bitmap bmp = Bitmap.createBitmap(mIntArray, width, height, Bitmap.Config.ARGB_8888); saveImage(bmp); 

This is the decodeYUV method:

  static public void decodeYUV420SP(int[] rgba, 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); // rgba, divide 2^10 ( >> 10) rgba[yp] = ((r << 14) & 0xff000000) | ((g << 6) & 0xff0000) | ((b >> 2) | 0xff00); } } } 

and this is the method that I call to save bitmap images to see how they look:

  private void saveImage(Bitmap bmp) { File myDir=new File("/sdcard/saved_images"); myDir.mkdirs(); Random generator = new Random(); int n = 10000; n = generator.nextInt(n); String fname = "Image-"+ n +".jpg"; File file = new File (myDir, fname); if (file.exists ()) file.delete (); try { FileOutputStream out = new FileOutputStream(file); bmp.compress(Bitmap.CompressFormat.JPEG, 90, out); out.flush(); out.close(); } catch (Exception e) { e.printStackTrace(); } } 

Here is the resulting image: https://docs.google.com/drawings/d/1kyIvb4oHHInW_c71mjfFSVCxVopBgBWX3k1OR_nMgRA/edit

0
android face-detection android-camera
source share
2 answers

So the problem was the decodeYUV method, which I got from another stackoverflow post here: Converting YUV-> RGB (image processing) β†’ YUV during onPreviewFrame in android? not quite working.

But I replaced this with what, in my opinion, should be the original decodeYUV method: http://code.google.com/p/android/issues/detail?id=823 up

0
source share

The key point here is that there is a (large) number of different YUV encodings and an even larger list of names used for them. A lot of information about all the different options (and their names) is given by fourcc , although the 420SP is not explicitly mentioned. If you look here , it looks like this:

  • 420P is the same as the YV12. A β€œP” appears to be in favor of a planar: there are three β€œplanes” of data one after the other: Y, U, and then V. (Or in YV21, which is also encoded 420P, Y, V, and then U.)
  • 420SP is the same as NV12 (it is the same as NV21 , but with U and V replaced). SP seems to be in favor of a half-plane, so 420SP can technically refer to NV21 or NV12.

In this case, you decode NV12 (unlike NV21), and therefore the order of U and V is exchanged compared to the answer that you quote in your answer . In case this helps, Here I have provided the code .

+1
source share

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


All Articles