I am developing an Android OpenCV app based on Opencv4android SDK tutorial 2 - Mixed Processing.
in the frame processing function public Mat onCameraFrame(CvCameraViewFrame inputFrame) {}
The frame is RGBA and I want to make RGB by doing this:
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
Mat mRgb=new Mat(640,480,CvType.CV_8UC3);
mRgba.convertTo(mRgb, CvType.CV_8UC3);
//Imgproc.cvtColor(mRgba, mRgb, CvType.CV_8UC3);
PinkImage(mRgb.dataAddr());
But when I debug and log the things I passed to the JNI part, I find it's not working at all.
mRgb is CV_8UC4 even after calling converto()
What is the cause of this?
OK, the answer is here
Imgproc.cvtColor(mRgba,mRgb,Imgproc.COLOR_RGBA2RGB);
instead of
mRgba.convertTo(mRgb, CvType.CV_8UC3);
Thanks a lot!!
You never use the converted data. You still pass mRgba.dataAddr() to PinkImage(), which is the unmodified RGBA image. You need to pass in the modified data:
PinkImage(mRgb.dataAddr());
Related
I am trying to process android video in real time with opencv-android. So far I am able to access the video with opencv, and display it on a org.opencv.android.JavaCameraView.(I referred to this link) I haven't been able to access the video feed of the camera by frame-wise. I need to get each and every frame in order to apply some opencv algorithms on them for object tracking. Please suggest a method to access and process the frames with opencv. (Redirect this if it's already been asked)
Here is how to do it:
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
//Do your processing here, for example:
Mat image = inputFrame.rgba();
Mat ret_mat=new Mat();
Core.add(image, new Scalar(40, 40, 40, 0), ret_mat); //change brightness of video frame
return ret_mat;
}
OpenCv functions operate with Mat object, which represents matrix of pixels of your image/frame. The code above makes each frame brighter by 40 units.
I'm newbie OCV and android developer. I want Imgproc.GaussianBlur filter in my app. When i use it application send "application stopped". I only add 3 lines to "OpenCV Tutorial 3 - Camera Control":
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat mat = inputFrame.gray();
org.opencv.core.Size s = mat.size();
Imgproc.GaussianBlur(mat, mat, s, 2);
return mat;
}
What could be wrong? I have Lenovo A820 Android 4.1.2 and tried it on OpenCV 2.4.4, 2.4.5 and 2.4.6. I tried different API. The Imgproc.Sobel(mat,mat,-1,1,1); filter works good.
look at the docs for GaussianBlur
it says: "ksize – Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd."
so, imho, you confused the kernel size with the Mat's size, try something like:
Mat mat = inputFrame.gray();
org.opencv.core.Size s = new Size(3,3);
Imgproc.GaussianBlur(mat, mat, s, 2);
return mat;
Currently trying
<code>
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
mRgba = inputFrame.rgba();
Imgproc.Canny(mRgba, markers, 80, 90);
Mat threeChannel = new Mat();
Imgproc.cvtColor(mRgba, threeChannel, Imgproc.COLOR_BGR2GRAY);
Imgproc.watershed(threeChannel, markers);
return threeChannel;
}
</code>
However, it fails with
CvException [org.opencv.core.CvException: /home/reports/ci/slave/50-SDK/opencv/modules/imgproc/src/segmentation.cpp:147: error: (-210) Only 8-bit, 3-channel input images are supported in function void cvWatershed(const CvArr*, CvArr*)
Could you advise how to appropriately use the markers from a Canny/Sobel edge detection to feed a Watershed algorithm? Android-specifics would be greatly helpful as this is my first Android project.
The error states that the input image for watershed() must be an 8-bit 3-channels image. After calling cvtColor(), print the number of channels of threeChannel. Don't be surprised if it outputs 1.
Pass mRgba directly to watershed() and see what happens. One of my previous answers have working code using watershed, you can use that for testing.
You need to just convert your image from 4 channel to 3 channels.
For example
Imgproc.cvtColor(mat , mat, Imgproc.COLOR_BGRA2BGR);
I'd like to initialize a 3 by 3 cross-shaped kernel matrix and use it to dilate an image in OpenCV4Android. In native C++ OpenCV, you'd do:
Mat kernel = (Mat_<int>(3,3) << 0,1,0,1,1,1,0,1,0);
dilate(image, image, kernel);
but how can I do the equivalent of the first line in Java? A Mat cannot be treated like an array, and Java has no << operator. There seems to be an OpenCV function called cvCreateStructuringElementEx which initializes Mats for use as kernels, but I can't find this function in OpenCV4Android.
Thanks so much.
I have never tried this but check if it works, at least this is the OpenCV4Android way to set a Structuring Element:
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3));
Also, check out copyTo() method, it can receive a Mask:
src_mat.copyTo(dst_mat, mask);
I am using OpenCV 2.3.1 in Android. I need to crop the image into half.
What I am doing is:
Mat mIntermediateMat2 = new Mat(frame_height,frame_width,rgba.type);
mIntermediateMat2 = rgba.clone();
mIntermediateMat2 = mIntermediateMat2.rowRange(0,frame_height/2);
Will the third step do the job or I have to add something more?
I saw Mat::operator() in opencv 2.3 documentation but unfortunately not able to find in the opencv Android package.
There are a few constructors for the Mat class, one of which takes a Mat and an ROI (region of interest).
Here's how to do it in Android/Java:
Mat uncropped = getUncroppedImage();
Rect roi = new Rect(x, y, width, height);
Mat cropped = new Mat(uncropped, roi);
I have always done cropping this way:
Mat image = ...; // fill it however you want to
Mat crop(image, Rect(0, 0, image.cols, image.rows / 2)); // NOTE: this will only give you a reference to the ROI of the original data
// if you want a copy of the crop do this:
Mat output = crop.clone();
Hope that helps!
Seems cv::getRectSubPix does what you want. Plus you don't have to allocate more space than you need. Also it does necessary interpolations if the cropped area is not aligned over an exact pixel.
This should do what you want. Input type will be the output type.
Mat dst;
getRectSubPix(src, Size(src.rows()/2,src.cols()), Point2f(src.rows()/4, src.cols()/2), dst);