How to scale a Mat in OpenCV - java

I'm frustrated trying to find a method that would allow me to scale a Mat object to a different size. Please, could anybody help me with this?
My project is using the Java wrapper, but I'll be happy if the answer provided is for the C++ native OpenCV library.

If by resizing you mean scaling an image use the resize() function as follows:
resize(src, dst, dst.size(), 0, 0, interpolation);
Otherwise if you just need to change the number of rows of your Mat use the Mat::reshape() function. Pay attention that the reshape return a new Mat header:
cv::Mat dst = src.reshape ( 0, newRowVal );
Finally if you want to arbitrarily reshape the Mat (changing rows and cols) you probably need to define a new Mat with the destination dimensions and copy the src Mat to it:
Mat dst(newRowVal, newColVal, src.type());
src.setTo(0);
src.copyTo(dst(Rect(Point(0, 0), src.size())));

You can use resize() function
Create a new Mat result of new dimensions
resize(input // input image
result // result image
result.size() // new dimensions
0,
0,
INTER_CUBIC // interpolation method
);
to know more interpolation methods, you can check this doc: geometric_transformations.html#resize

Related

How to get connectedComponents with stats in android java using opencv and how to use these stats to get left point, right pint, centroid, area etc

Please clear I am new at android and java
I have used this code but don't know what is meaning of these four variables
Imgproc.connectedComponentsWithStats(binarized, labeled, rectComponents, centComponents);
Mat tmp = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8U);
Utils.bitmapToMat(bmp, tmp);
Imgproc.cvtColor(tmp, tmp, Imgproc.COLOR_RGB2GRAY);
Imgproc.threshold(tmp, tmp, 40, 255, Imgproc.THRESH_BINARY);
Imgproc.GaussianBlur(tmp, tmp, new org.opencv.core.Size(5, 5), 0 , 0);
Imgproc.threshold(tmp,tmp,130,255,Imgproc.THRESH_OTSU);
Utils.matToBitmap(tmp, bmp);
imageView.setImageBitmap(bmp);```
I want to get connected components with stats of tmp.
Thanks guys, I am answering my own question. I have found how to do it.
int a = Imgproc.connectedComponentsWithStats(image,labels,stats,centroid);
this function returns an integer which is the number of connected components in the image(Mat OpenCV) which is passing to the function (first argument).
labels is a Mat datatype array which is of the size of the input image with the value of each pixel is label of that pixel in the original image
centroid is centroid of each label(x,y).
stats tells us area of the label and position of the label(return leftmost pixel, topmost pixel,width,height)

Join different sized images with ROI

At the first contact with Java OpenCV (3.3.1, windows 8 x64) I'm trying to join two different size images with ROI dynamically. Here a bit of my code:
Mat _mat = Utils.imageFileToMat(new File("angelina_jolie.jpg")); //Angelina's face
Mat grayMat = new Mat();
Imgproc.cvtColor(_mat, grayMat, Imgproc.COLOR_BGR2GRAY);
Rect rect = new Rect(new Point(168, 104), new Point(254, 190)); //Angelina's eye ROI
Mat truncated = _mat.submat(rect); //Angelina's eye mat
Mat merge = _mat.clone();
truncated.copyTo(merge);
//show _mat
//show truncated
//show merge
What I want to see is Angelina Jolie with her eye on grayscale.
What I see is assertions or the truncated image only (just the eye).
I tried with copyTo(mat, mask), setOf, and a lot of things but always get a new assertion.
Should I change the size of truncated to the size of mat to match sizes? how can I do that programmatically?
Mat::copyTo documentation:
The method copies the matrix data to another matrix. Before copying
the data, the method invokes :
m.create(this->size(),this->type());
so that the destination matrix is reallocated
if needed. While m.copyTo(m); works flawlessly, the function does not
handle the case of a partial overlap between the source and the
destination matrices.
When the operation mask is specified, if the Mat::create call shown
above reallocates the matrix, the newly allocated matrix is
initialized with all zeros before copying the data.
#param m
Destination matrix. If it does not have a proper size or type before
the operation, it is reallocated.
Since you're your src and dst images don't have the same size and channels, the destination image is reallocated and initialized with zeros. To avoid that make sure both images have same dimensions and number of channels.
Imgproc.cvtColor(grayMat, grayMat, Imgproc.COLOR_GRAY2BGR);
Now create a mask:
Mat mask = new Mat(_mat.size(), CvType.CV_8UC1, new Scalar(0));
Imgproc.rectangle(mask, new Point(168, 104), new Point(254, 190),new Scalar(255));
// copy gray to _mat based on mask
Mat merge = _mat.clone();
grayMat.copyTo(merge,mask);

color detection using opencv

I am trying to extract the title bar from the image below using opencv.
I am using the following code -
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat original = Imgcodecs.imread("D:/test_bg_extract.png", Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
Mat hsvMat = new Mat();
Imgproc.cvtColor(original, hsvMat, Imgproc.COLOR_BGR2HSV);
Mat dst = new Mat();
Core.inRange(hsvMat, new Scalar(23,231,205), new Scalar(23,231,205), dst);
I used a color picker to determine the HSV value of the title bar (from the hsvMat converted to display image). When the run the code to display the output, I see a blank screen. I can't tell what I am doing wrong. Am I picking the wrong HSV color? If I know the exact RGB code then should I even be converting image to HSV? (this however seems to be the standard method from many code examples on the internet).
Ok, I solved it using RGB based color, switching to BGR while specifying the color that I need. So this worked -
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat original = Imgcodecs.imread("D:/test_bg_extract.png", Imgcodecs.CV_LOAD_IMAGE_UNCHANGED);
Mat dst = new Mat();
Core.inRange(original, new Scalar(132,178,205), new Scalar(132,178,205), dst);

Imgproc.drawContours(....) not showing up

In my android app I get an image from the gallery as a bitmap with something like this
Bitmap bitm = getMyImage("Thanks!");
and I have a Mat called mat declared like this:
Mat mat = new Mat(bitm.getHeight(), bitm.getWidth(), CVType.CV_8UC3);
I'm trying to get contour areas from the image, which I've successfully gotten then draw it back on the original image with:
Imgproc.drawContours(mat, contours, -1, new Scalar(200,200,0), 2);
displayMat(mat);
If I use it like that, it works but the contours are drawn on a blank image which isn't what I want. I want it to be drawn on the original image. If I use
Utils.bitmapToMat(bitm, mat);
before the previous snippet of code, the displayed image is just the preprossed image without the 'Drawn' contours. Why?
Asfaik Android uses images with alpha values, so CV_8UC4 is the right data type.
So
Mat mat = new Mat(bitm.getHeight(), bitm.getWidth(), CVType.CV_8UC3);
Imgproc.drawContours(mat, contours, -1, new Scalar(200,200,0), 2);
displayMat(mat);
draws the contours correctly on an empty/blank 8UC3 image (if memory empty).
But if you want to draw on the input image by first converting Utils.bitmapToMat(bitm, mat); you'll overwrite your 8UC3 memory and replace it by 8UC4 data. After that you draw Scalar(200,200,0) which will use a 4th channel, but cv::Scalar automatically adds those channels with default zero values, so you draw your contours in transparent. So use Scalar(200,200,0,255) instead and it should give your expected results.
Mat mat = new Mat(bitm.getHeight(), bitm.getWidth(), CVType.CV_8UC3);
Utils.bitmapToMat(bitm, mat);
Imgproc.drawContours(mat, contours, -1, new Scalar(200,200,0,255), 2);
displayMat(mat);
The other method would be to convert the bitmap to 8UC3, but I'm not sure how to do that.

How to create a Raster from a pixel float array in Java?

I'm trying to take a BufferedImage, apply a Fourier transform (using jtransforms), and write the data back to the BufferedImage. But I'm stuck creating a new Raster to set the results back, am I missing something here?
BufferedImage bitmap;
float [] bitfloat = null;
bitmap = ImageIO.read(new File("filename"));
FloatDCT_2D dct = new FloatDCT_2D(bitmap.getWidth(),bitmap.getHeight());
bitfloat = bitmap.getData().getPixels(0, 0, bitmap.getWidth(), bitmap.getHeight(), bitfloat);
dct.forward(bitfloat, false);
But I'm stumped trying to finish off this line, what should I give the createRaster function? The javadocs for createRaster make little sense to me:
bitmap.setData(Raster.createRaster(`arg1`, `arg2`, `arg3`));
I'm starting to wonder if a float array is even necessary, but there aren't many examples of jtransforms out there.
Don't create a new Raster. Use WritableRaster.setPixels(int,int,int,int,float[]) to write the array back to the image.
final int w = bitmap.getWidth();
final int h = bitmap.getHeight();
final WritableRaster wr = bitmap.getData();
bitfloat = wr.getPixels(0, 0, w, h, bitfloat);
// do processing here
wr.setPixels(0, 0, w, h, bitfloat);
Note also that if you're planning to display this image, you should really copy it to a screen-compatible type; ImageIO seldom returns those.
I'm doing Google searches for FloatDCT_2D to see what package/library it's in, and it looks like there are several references to various sources, such as "edu.emory.mathcs.jtransforms.dct.FloatDCT_2D". Without knowing what custom library you're using, it's really hard to give you any advice on how to perform the transform.
My guess is in general, that you should read the input data from the original raster, perform the transform on the original data, then write the output to a new raster.
However, your last statement all on it's own looks odd... Raster.createRaster() looks like you're calling a static method with no parameters on a class you've never referenced in the code you've posted. How is that generating data for your bitmap??? Even in pseudo code, you would need to take the results of your transform and build the resultant raster.

Categories