I have square area for detection and I replace square area with image but now I have a problem because the image is too large for the square area. So I'd like to resize the image in order to has the same size with the square area.
How I can resize the image? You can look at my GIF below this post
My Code:
Core.rectangle(rgbaInnerWindow, new Point(pt.x-radius,pt.y-radius), new Point(pt.x+radius,pt.y+radius), new Scalar(255));
Mat mask = new Mat(rgbaInnerWindow.size(), CvType.CV_8UC1);
Mat dst = new Mat();
Imgproc.resize(img1, dst, mask.size());
dst.copyTo(rgbaInnerWindow);
Related
i want to crop the circles i detected using hough transform, i succeded to detect the circles but i didnt understand how to crop them.
here is the code i used for hough transform:
for( int i=0;i<circles.cols();i++){
Point center = new Point( Math.round(circles.get(0,i)[0]),
Math.round(circles.get(0, i)[1]));
System.out.println("X============="+i+":"+circles.get(0,i)[0]);
System.out.println("Y============="+i+":"+circles.get(0,i)[1]);
int radius = (int) Math.round(circles.get(0, i)[2]);
//System.out.println("--Rayon--:"+radius);
Imgproc.circle( image, center, radius, new Scalar(0,0,255),3);//radius, color) `
You can crop an image like this:
Mat initialImage = ...
Rect crop = new Rect(new Point(column,row),new Size(width,height)); // crop area begins at Point(column,row) with Size(width,height)
Mat croppedImage = new Mat(initialImage,crop);
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);
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.
I'm currently working on a program that should draw a small image onto the camera frame. With Android OpenCV, you do have the following function to process a frame:
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat rgba = inputFrame.rgba();
mDetector.setFrame(rgba);
mDetector.processFrame();
return rgba;
}
Where the Mat rgba then gets displayed on the screen. My Detector should now process the frame rgba (change it).
Here is the relevant code:
public void processFrame() {
// (1) Doesn't work
Rect roi = new Rect(0, 0, 100, 100);
Mat submat = mOutputFrame.submat(roi);
Mat image = new Mat(100, 100, CvType.CV_8UC3, new Scalar(0,0,0));
image.copyTo(submat);
// (2) Does work
// --- mComparatorImage is the same size as mOutputFrame.
// --- mComparatorImage is 8bit greyscale, mOutputFrame is the rgba CameraFrame
mComparatorImage = mComparatorHolder.getCurrentImage();
mComparatorImage.copyTo(mOutputFrame);
// (3) Should work (but doesn't)
Imgproc.resize(mComparatorImage, mResizedImageClone, new Size (200, 100));
Mat bSubmat = mOutputFrame.submat(new Rect(0, 0, 200, 100));
mResizedImageClone.copyTo(bSubmat);
}
What I'm trying to do is to copy a resized version of mComparatorImage into the camera frame that is referenced by mOutputFrame (mOutputFrame = rgba).
So I tried doing (3).
FYI: mResizedImageClone is of type Mat and is initialized as a new Mat()
Doing (3) doesn't change the mOutputFrame.
(2) Then I tried copying the whole mComparatorImage (type Mat and same size as mOutputFrame) to mOutputFrame. This worked suprisingly.
(1) Then I thought the problem has to be something with submat, because copying the big image works, but copying a small version of it into mOutputFrame doesnt. So I tried copying a little black image into mOutputFrame. This doesn't work either, although I followed other answers here.
What could be the problem? There is no error, but the camera frame stays the same in (1) and (3)
If you need any additional info, let me know.
Isa
Okay, I've found it, it was a little bit tricky.
The copyTo function using submatrices works only properly if the src and the dest Mat are of the same type. Otherwise, it just does ... nothing. (It rather should complain!)
Instead of using rect, I used submat with parameters (row_start, row_end, col_start, col_end)
Also be aware that the dimensions of the submat (#cols and #rows) have to exactly match the src image that is used in copyTo.
So here is my solution for (1):
// (1) Inserting a little black rect into the camera frame:
Mat submat = mOutputFrame.submat(0, 100, 0, 100);
Mat image = new Mat(100, 100, mOutputFrame.type(), new Scalar(0,0,0));
image.copyTo(submat);
And my solution for (3):
// (3) Resizing and inserting an arbitrary grey image into the rgba camera frame
Imgproc.resize(mComparatorImage, mResizedImageClone, new Size (200, 100));
Imgproc.cvtColor(mResizedImageClone, mResizedImageClone, Imgproc.COLOR_GRAY2RGBA);
Mat submat = mOutputFrame.submat(0, 100, 0, 200);
mResizedImageClone.copyTo(submat);
I am aware of BufferedImage.getSubimage However, it cant deal with cropping images that are smaller than the cropping size throwing the exception:
java.awt.image.RasterFormatException: (y + height) is outside raster
I want to be able to crop either a PNG/JPG/GIF to a certain size however if the image is smaller than the cropping area centre itself on a white background. Is there a call to do this? Or do I need to create an image manually to centre the image on if so, how would I go about this?
Thanks
You cannot crop an image larger, only smaller. So, you start with the goal dimension,let's say 100x100. And your BufferedImage (bi), let's say 150x50.
Create a rectangle of your goal:
Rectangle goal = new Rectangle(100, 100);
Then intersect it with the dimensions of your image:
Rectangle clip = goal.intersection(new Rectangle(bi.getWidth(), bi.getHeight());
Now, clip corresponds to the portion of bi that will fit within your goal. In this case 100 x50.
Now get the subImage using the value of clip.
BufferedImage clippedImg = bi.subImage(clip,1, clip.y, clip.width, clip.height);
Create a new BufferedImage (bi2), the size of goal:
BufferedImage bi2 = new BufferedImage(goal.width, goal.height);
Fill it with white (or whatever bg color you choose):
Graphics2D big2 = bi2.getGraphics();
big2.setColor(Color.white);
big2.fillRect(0, 0, goal.width, goal.height);
and draw the clipped image onto it.
int x = goal.width - (clip.width / 2);
int y = goal.height - (clip.height / 2);
big2.drawImage(x, y, clippedImg, null);