does anybody know what pixel type does BitmapFactory.decodeByteArray() returns?
basicly i'm using this snippet on the camera preview callback:
YuvImage img = new YuvImage(mLastFrame, ImageFormat.NV21, mPreviewSize.width, mPreviewSize.height, null);
ByteArrayOutputStream out = new ByteArrayOutputStream();
img.compressToJpeg(new Rect(0,0,mPreviewSize.width, mPreviewSize.height), 30, out);
return BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());
i get a good Bitmap which i can use with android. but if i want to use it with OpenCV, it doesn't work, and as OpenCV requires an ARGB_8888 type, i'm guessing, i get another type from the decodeByteArray() function.
thanks,
Vlad
You can use Bitmap.getConfig() on your resulting Bitmap and see if it is ALPHA_8, RGB_565 etc...
Related
I want to use CameraSource to detect some visual code (which is not any kind of Barcode). I implements Detector and its detect(Frame frame) method. However, when I call frame.getBitmap() in the detect method, it always returns null. I know Frame has another method, getGrayscaleImageData(), but detecting the code needs color information. It seems that CameraSource only pass the gray-scale image data to its underlying detector.
So, is there a way to detect this code by CameraSource? Or should I abandon CameraSource and find another way?
In the current release, CameraSource actually does return the full color information for the image from getGrayscaleImageData. The leading bytes of what is returned is the grayscale layer of the image (the Y channel), but the bytes beyond that have the color information. The format details depend upon what image format you specified in setting up the CameraSource (the default is NV21 format).
Found it :D
this code return colored bitmap so fast but if it's the Front camera you may have to flip/rotate according to device.
public SparseArray detect(Frame frame) {
byte[] bytes = frame.getGrayscaleImageData().array();
YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, frame.getMetadata().getWidth(), frame.getMetadata().getHeight()), 100, byteArrayOutputStream);
byte[] jpegArray = byteArrayOutputStream.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);//this bitmap is colored.
return null;
}
I was struggeling to get YuvImage to a png imageformat on an Android 5.0.1 device where the png showed up as green images. On a Android 5.1.1 this did not happend, and the images was showing just fine.
After some time I found out that there is a bug in Android 5.0.1 which makes the images that are converted appear green. This was fixed in Android 5.1.1
However, does anyone know about a solution in order to make this work on devices that has not got this fix?
I don't think there is a way to workaround the bug because in my experience the images are already green when generated by the system, and it is not a problem of the conversion to PNG.
I see that you are using the Camera 2 API from your comment response, and since you are using YUV format I believe you are trying to save images from the continuous feed from the camera (as opposed from full resolution picture taking). If that is the case, I'll suggest using the older Camera API if at all possible, as I haven't seen a device that does not work when capturing preview images in YUV format (NV21), which can easily converted to a PNG, although having to go through a JPEG step:
YuvImage yuvImage = new YuvImage(nv21bytearray, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream os = new ByteArrayOutputStream();
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, os);
byte[] jpegByteArray = os.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(jpegByteArray, 0, jpegByteArray.length);
FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory() + "/imagename.png");
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
with nv21bytearray being the NV21 byte array returned by the old camera API onPreviewFrame(...) method.
I am trying to load images into a Mat in openCV for Android for face recognition.
The images are in in jpeg format of size 640 x 480.
I am using Eclipse and this codes are in .cpp file.
This is my codes.
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, ',');
getline(liness, classlabel);
if(!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
However, I am getting an error saying that "The matrix is not continuous, thus its number of rows cannot be changed in function cv::Mat cv:Mat:reshape(int,int)const"
I tried using the solution in OpenCV 2.0 C++ API using imshow: returns unhandled exception and "bad-flag"
but it's in Visual Studio.
Any help would be greatly appreciated.
Conversion of image from Camera preview.
The image is converted to Grayscale from camera preview data.
Mat matRgb = new Mat();
Imgproc.cvtColor(matYuv, matRgb, Imgproc.COLOR_YUV420sp2RGB, 4);
try{
Mat matGray = new Mat();
Imgproc.cvtColor(matRgb, matGray, Imgproc.COLOR_RGB2GRAY, 0);
resultBitmap = Bitmap.createBitmap(640, 480, Bitmap.Config.ARGB_8888);
Utils.matToBitmap(matGray, resultBitmap);
Saving image.
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmFace[0].compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] flippedImageByteArray = stream.toByteArray();
the 'Mat not continuous' error is not at all related to the link you have there.
if you're trying fisher or eigenfaces, the images have to get 'flattened' to a single row for the pca.
this is not possible, if the data has 'gaps' or was padded to make the row size a multiple of 4. some image editors do that to your data.
also, imho your images are by far too large ( pca works best, when it'S almost quadratic, ie the rowsize (num_pixels) is similar to the colsize(num_images).
so my proposal would be, to resize the train images ( and also the test images later ) to something like 100x100, when loading them, this will also achieve a continuous data block.
(and again, avoid jpegs for anything image-processing related, too many compression artefacts!)
I have a loaded Bitmap which I would like to convert to set the config to Bitmap.Config.RGB_565. Is there a simple way of converting a Bitmap to this configuration after the Bitmap is already loaded into memory? For example, below I have a bitmap being decoded from the application resources, however, how would I convert an already loaded Bitmap to RGB_565? I'm sure it's something simple, however, I'm fairly new to working with Bitmaps and after a few hours of looking online, unfortunately I couldn't find what I needed specifically.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig=Bitmap.Config.RGB_565
bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.myphoto ,options);
You can also try this:
Bitmap converted = original.copy(Config.RGB_565, false);
From the documentation of Bitmap.copy():
Tries to make a new bitmap based on the dimensions of this bitmap, setting the new bitmap's config to the one specified, and then copying this bitmap's pixels into the new bitmap. If the conversion is not supported, or the allocator fails, then this returns NULL.
Looking through the native source code, you should be fine converting between any values of Bitmap.Config.
I haven't tested this but it should work:
private Bitmap convert(Bitmap bitmap, Bitmap.Config config) {
Bitmap convertedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), config);
Canvas canvas = new Canvas(convertedBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawBitmap(bitmap, 0, 0, paint);
return convertedBitmap;
}
call the methods like this:
Bitmap convertedBitmap = convert(bitmap, Bitmap.Config.RGB_565);
You can do all kinds of additional transformations like rotating, stretching etc. if you use the drawBitmap with a Matrix.
Found the answer here https://stackoverflow.com/a/12148450/1364673, thanks to
siliconeagle.
The solution is to create a new bitmap with the required encoding as per link above example.
It's well documented that Android's camera preview data is returned back in NV21 (YUV 420). 2.2 added a YuvImage class for decoding the data. The problem I've encountered is that the YuvImage class data appears corrupt or incorrect. I used the Renderscript Sample app called HelloCompute which transforms a Bitmap into a mono-chrome Bitmap. I used two methods for decoding the Preview data into a Bitmap and passing it as input to the Renderscript:
Method 1 - Android YuvImage Class:
YuvImage preview = new YuvImage(data, ImageFormat.NV21, width, height, null);
ByteArrayOutputStream mJpegOutput = new ByteArrayOutputStream(data.length);
preview.compressToJpeg(new Rect(0, 0, width, height), 100, mJpegOutput);
mBitmapIn = BitmapFactory.decodeByteArray( mJpegOutput.toByteArray(), 0, mJpegOutput.size());
// pass mBitmapIn to RS
Method 2 - Posted Decoder Method:
As posted over here by David Pearlman
// work around for Yuv format </p>
mBitmapIn = Bitmap.createBitmap(
ImageUtil.decodeYUV420SP(data, width, height),
width,
height,
Bitmap.Config.ARGB_8888);
// pass mBitmapIn to RS
When the image is processed by the Renderscript and displayed Method 1 is very grainy and not mono-chrome, while Method 2 produces the expected output, a mono-chrome image of the preview frame. Am I doing something wrong or is the YuvImage class not usable? I'm testing this on a Xoom running 3.1.
Furthermore, I displayed the bitmaps produced by both methods on screen prior to passing to the RS. The bitmap from Method 1 has noticeable differences in lighting (I suspected this was due to the JPeg compression), while Method 2's bitmap is identical to the Preview Frame.
There is no justification for using Jpeg encode/decode just to convert a YUV image to a grayscale bitmap (I believe you want grayscale, not monochrome b/w bitmap after all). You can find many code samples that produce the result you need. You may use this one: Converting preview frame to bitmap.