Extract Black and White Image from Android Camera's Nv21 Format

How to get the center of a YUV image without processing the rest?

Using this guide here;
stackoverflow.com/questions/5272388/extract-black-and-white-image-from-android-cameras-nv21-format

Explains the process fairly well.
However, it seems I was having a different problem then I expected,but its different enough to repost the question.

Converting YUV-RGB(Image processing)-YUV during onPreviewFrame in android?

Why not specify that camera preview should provide RGB images?

i.e. Camera.Parameters.setPreviewFormat(ImageFormat.RGB_565);

NV21 format and odd image dimensions

In the case of an image with odd dimensions (i.e one of W or H, in a WxH image is odd), you'd expect the Y plane to be fully sampled as always, with WxH samples, followed by 2(⌈W/2⌉ x ⌈H/2⌉) chroma samples, where we divide each image dimension by 2 but round up rather than round down.

So some of the pixels at the very edge of the image have chroma samples that correspond to only 1 or 2 original pixels, rather than 4. I hope that makes sense. You can see in this link that a couple of other libraries have had issues handling odd dimensions in YUV images previously.

For your second question, I haven't seen an official specification, but I have seen some code in the android framework that handles this format, I will see if I can dig up a link to it, and append it to this answer.

I try to create a bitmap from a YUV Image, but the image looks distorted (has green and pink overlay)

The image you attached is very low quality 320x180 I420.

Working with raw imageData in onPictureTaken

I realize this answer is a bit late, but here's what I have learned over the past month, while working with the camera.

Whether you receiver raw image data via onPictureTaken or onPreviewFrame it can come encoded in sereral different formats (android.graphics.ImageFormat). The only one that is guaranteed universal support (according to the docs) is NV21, YV12 is universally supported from honeycomb and up. Besides being universally supported, NV21 might fit very well to what you're trying to do (convert into black and white). NV21 is a YUV format, where the Y channel carries luminosity information, while U and V channels carry color information. See a more formal description here:

http://en.wikipedia.org/wiki/YUV

http://www.fourcc.org/fccyvrgb.php

http://www.fourcc.org/yuv.php#NV21

The wiki link has a sample source that achieves NV21->RGB conversion (not very efficient as is, but gives a good idea of the general approach). Should you be interested in doing this conversion in C or assembly, this was a good source of info (warning: there is no code for NV21, and my quick modifications to handle NV21 led to nothing good). Nevertheless, it shows how to incorporate .S files into ndk projects, which is actually really easy.

http://www.roman10.net/effective-color-conversion-yuv-rgb-in-android-in-assembly/

Back to your question - conversion into B/W. Simply take the Y channel and form RGB triples as [Y,Y,Y] and that will give you a black and white image. Or maybe simply make an L8 image out of it (eg, Y->L).

PS.
There is a great deal of confusion regarding range/scaling of YUV values during transformation to RGB. I found that camera data comes in full-swing (0-255, not 16-235 or 16-240), and that clamping the result to 0-255 after matrix multiplication gives a visually pleasing result, while scaling to 0-255 distorts the colors (needless to say, this is still true if you scale to some other range, such as 16-240). These observations appear to go against some of the finer aspects of the full transformation procedure described in the links above, but that's what I found to work.



Related Topics



Leave a reply



Submit