What does the submat function do in OpenCV-Android? - android

What does the submat function do in OpenCV-Android?
I am trying to understand a code that I found that really does the functionality I am looking for, which I perfectly understand the code except for the 'Submat' function since in the documentation I cannot find its detail of the parameters
Mat zoomCorner = rgba.Submat(0, rows / 2 - rows / 10, 0, cols / 2 - cols / 10);

Mat object in OpenCV use reference counting approach.
Mat has reference to buffer and buffer parameters.
When you use submat(), you get new Mat that shares image data buffer with original Mat.
You need to copy ROI to new Mat with Mat::copyTo() method and make all calculations with submat() copy.

Related

Thresholding in Android using opencv

Not sure if this is the right way to ask, but please help. I have an image of a dented car. I have to process it and highlight the dents and return the number of dents. I was able to do it reasonably well with the following result:
The matlab code is:
img2=rgb2gray(i1);
imshow(img2);
img3=imtophat(img2,strel('disk',15));
img4=imadjust(img3);
layer=img4(:,:,1);
img5=layer>100 & layer<250;
img6=imfill(img5,'holes');
img7=bwareaopen(img6,5);
[L,ans]=bwlabeln(img7);
imshow(img7);
I=imread(i1);
Ians=CarDentIdentification(I);
However, when I try to do this using opencv, I get this:
With the following code:
Imgproc.cvtColor(source, middle, Imgproc.COLOR_RGB2GRAY);
Imgproc.equalizeHist(middle, middle);
Imgproc.threshold(middle, middle, 150, 255, Imgproc.THRESH_OTSU);
Please tell me how can I obtain better results in opencv, and also how to count the dents? I tried findcontour() but it gives a very large number. I tried on other images as well, but I'm not getting proper results.
Please help.
So you basically from the MATLAB site, imtophat does - Top-hat filtering computes the morphological opening of the image (using imopen) and then subtracts the result from the original image.
You could do this in OpenCV with the following steps:
Step 1: Get the disk structuring element
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
Step 2: Compute opening of the image and then subtract the result from the original image
tophat = cv2.morphologyEx(v, cv2.MORPH_TOPHAT, kernel)
This gives following result -
Step 3 - Now you could just manually threshold it or use Otsu -
ret, thresh = cv2.threshold(tophat, 17, 255, 0)
which gives you the following image -
Since the OP wants the code in Java, here is the probable code in Java:
private Mat topHat(Mat image)
{
Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(15, 15), new Point (0, 0));
Mat dst = new Mat;
Imgproc.morphologyEx(image, dst, Imgproc.MORPH_TOPHAT, element, new Point(0, 0));
return dst;
}
Make sure you do this on a gray scale image (CvType.8UC1) and then you can threshold suitably.

OpenCV for Android - initialize Matrix

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);

How can I perform face recognition using an eigenfaces value in OpenCV?

After using OpenCV's PCACompute function as shown below, I have a Mat representing mean and a Mat of eigenvectors.
org.opencv.core.Core.PCACompute(datiOriginali,mean, eigenvectors,0);
datiOriginali is my input Mat, mean is the mean value Mat and eigenvectors is the eigenvectors Mat.
From there, I used PCAProject thus:
org.opencv.core.Core.PCAProject(datiOriginali, mean,eigenvectors , res);
datiOriginali is always the input Mat, mean and eigenvectors are the same as were calculated in PCACompute and res is the output Mat.
How can I perform face recognition using an eigenfaces value? I don't know how to calculate the Euclidean distance between a training image calculated as shown above and a new image.

OpenCV for Android: how to copy a Mat object (image) to another Mat?

Both Mat objects contain (different) images. I want to copy mSnapshot over mRgba.
I tried these (separately), but none of them seem to change mRgba:
mSnapshot.assignTo(mRgba);
mSnapshot.copyTo(mRgba);
mRgba = mSnapshot;
This throws an exception:
mRgba.setTo(mSnapshot);
And this does work, and sets mRgba to be a completely black image:
mRgba.setTo(new Scalar(0,0,0,255));
What am I missing?
[Edit]
The source files and exception can be found here.
To copy an image, you should use the clone() member function like this:
capture.retrieve(mSnapshot, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
mRgba = mSnapshot.clone();
Another note, OpenCV stores information in BGR order; therefore, your line:
mRgba.setTo(new Scalar(0,0,0,255));
Edited for clarity : This command is setting each pixel to (0, 0, 0, 255), so channels 1-3 are set to 0, and channel 4 (alpha) is set to 255. What if you tried this:
mRgba.setTo(new Scalar(0, 255, 0, 0)); // should be set to green.
Also, note that you can only use setTo once the matrix is allocated.
Hope that helps!

Cropping image in Android using opencv

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);

Categories

Resources