I am working with OpenCV library in Android. I have a class which implements PictureCallBack
.
The override method onPictureTaken()
is as g
opencv has a neat way to writing Mats to files - it can generate different formats based on the file extension provided. Here is a minimal example:
public void writeImageToFile(Mat image, String filename) {
File root = Environment.getExternalStorageDirectory();
File file = new File(root, filename);
Highgui.imwrite(file.getAbsolutePath(), image);
if (DEBUG)
Log.d(TAG,
"writing: " + file.getAbsolutePath() + " (" + image.width()
+ ", " + image.height() + ")");
}
if red and blue is swapped then it sounds like your byte data from onPictureTaken() is in BGRA format. You can swap it to RGBA using:
Imgproc.cvtColor(bgrImg, rgbImg, Imgproc.COLOR_BGR2RGB);
the format is actually device specific - on one device I had it comes through as YUV.
You can use the imdecode method which comes as part of opencv (this is for emgucv but it should have a similar operation on other versions of opencv, syntax might just be different)
Example:
byte [] imageArray
Mat dest
CvInvoke.Imdecode(imageArray, ImreadModes.Unchanged, dest)
For me, the next works fine for me:
Java side:
Bitmap bitmap = mTextureView.getBitmap(mWidth, mHeight);
int[] argb = new int[mWidth * mHeight];
// get ARGB pixels and then proccess it with 8UC4 OpenCV convertion
bitmap.getPixels(argb, 0, mWidth, 0, 0, mWidth, mHeight);
// native method (NDK or CMake)
processFrame8UC4(argb, mWidth, mHeight);
OpenCV side (NDK):
JNIEXPORT jint JNICALL com_native_detector_Utils_processFrame8UC4
(JNIEnv *env, jobject object, jint width, jint height, jintArray frame) {
jint *pFrameData = env->GetIntArrayElements(frame, 0);
// it is the line:
Mat mFrame = Mat(height,width,CV_8UC4,pFrameData).clone();
// your code..
env->ReleaseIntArrayElements(frame, pFrameData, 0);
}
The best and easiest way is like this:
byte[] bytes = FileUtils.readFileToByteArray(new File("aaa.jpg"));
Mat mat = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
You have to specify width and height of the image/Mat and channels depth.
Mat mat = new Mat(width, height, CvType.CV_8UC3);
mat.put(0, 0, data);
Make sure you are using correct type of Mat. Maybe your data is not in 3 bytes RGB format and you should use another type e.g. CvType.CV_8UC1
.
Good luck!