Find the center of a shape (path) on a canvas (Android Studio) - android

Is it possible to find the center of a shape on a canvas in Android studio? I've logged the touch points and can't seem to figure it out. It does however appear that the canvas (0,0) point is the top left, but the paths/shapes on the canvas see the center point as (0,0).
For an example of what I'm talking about check out the attached image, I'm trying to find where the green dot is.
Thanks in advance for any help.
IMG

To find the center of a Path use the method computeBounds(bounds,exact) which will set the first argument RectF bounds to the extent of the Path. Then it is just a matter of getting the mean of the left right and top bottom coordinates to get the geometric center of the path.
// mPath is your path. Must contain more than 1 path point
RectF bounds = new RectF();
mPath.computeBounds(bounds, false); // fills rect with bounds
PointF center = new PointF((bounds.left + bounds.right) / 2,
(bounds.top + bounds.bottom) / 2);

No Need for Mathematical Calculations
RectF bounds = new RectF();
mPath.computeBounds(bounds, false);
float centerX = rectF.centerX();
float centerY = rectF.centerY();

Related

Blurring a region in an image on Android (in Java)

In my Android app, I am capturing a screenshot programmatically from a background service. I obtain it as a Bitmap.
Next, I obtain the co-ordinates of a region of interest (ROI) with the following Android framework API:
Rect ROI = new Rect();
viewNode.getBoundsInScreen(ROI);
Here, getBoundsInScreen() is the Android equivalent of the Javascript function getBoundingClientRect().
A Rect in Android has the following properties:
rect.top
rect.left
rect.right
rect.bottom
rect.height()
rect.width()
rect.centerX() /* rounded off to integer */
rect.centerY()
rect.exactCenterX() /* exact value in float */
rect.exactCenterY()
What does top, left, right and bottom mean in Android Rect
object
Whereas a Rect in OpenCV has the following properties
rect.width
rect.height
rect.x /* x coordinate of the top-left corner */
rect.y /* y coordinate of the top-left corner */
Now before we can perform any OpenCV-related operations, we need to transform the Android Rect to an OpenCV Rect.
Understanding how actually drawRect or drawing coordinates work in Android
There are two ways to convert an Android Rect to an OpenCV Rect (as suggested by Karl Phillip in his answer). Both generate the same values and both produce the same result:
/* Compute the top-left corner using the center point of the rectangle. */
int x = androidRect.centerX() - (androidRect.width() / 2);
int y = androidRect.centerY() - (androidRect.height() / 2);
// OR simply use the already available member variables:
x = androidRect.left;
y = androidRect.top;
int w = androidRect.width();
int h = androidRect.height();
org.opencv.core.Rect roi = new org.opencv.core.Rect(x, y, w, h);
Now one of the OpenCV operations I am performing is blurring the ROI within the screenshot:
Mat originalMat = new Mat();
Bitmap configuredBitmap32 = originalBitmap.copy(Bitmap.Config.ARGB_8888, true);
Utils.bitmapToMat(configuredBitmap32, originalMat);
Mat ROIMat = originalMat.submat(roi).clone();
Imgproc.GaussianBlur(ROIMat, ROIMat, new org.opencv.core.Size(0, 0), 5, 5);
ROIMat.copyTo(originalMat.submat(roi));
Bitmap blurredBitmap = Bitmap.createBitmap(originalMat.cols(), originalMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(originalMat, blurredBitmap);
This brings us very close to the desired result. Almost there, but not
quite. The area just BENEATH the targeted region is blurred.
For example, if the targeted region of interest is a password field, the above code produces the following results:
On the left, Microsoft Live ROI, and on the right, Pinterest ROI:
As can be seen, the area just below the ROI gets blurred.
So my question is, finally, why isn't the exact region of interest
blurred?
The co-ordinates obtained through the Android API getBoundsInScreen() appear to be correct.
Converting an Android Rect to an OpenCV Rect also appears to be correct. Or is it?
The code for blurring a region of interest also appears to be correct. Is there another way to do the same thing?
N.B: I've provided the actual, full-size screenshots as I am getting them. They have been scaled down by 50% to fit in this post, but other than that they are exactly as I am getting them on the Android device.
If I'm not mistaken, OpenCV's Rect assumes that x and y specify the top left corner of the rectangle:
/* Compute the top-left corner using the center point of the rectangle
* TODO: take care of float to int conversion
*/
int x = androidRect.centerX() - (androidRect.width() / 2);
int y = androidRect.centerY() - (androidRect.height() / 2);
// OR simply use the already available member variables:
x = androidRect.left;
y = androidRect.top;
int w = androidRect.width();
int h = androidRect.height();
org.opencv.core.Rect roi = new org.opencv.core.Rect(x, y, w, h);
As per ScreenShots the value you get fot rect.x is not same for opencv rect.
Because android rect center x value get from pixel density of screen while opencv rect value react image pixel row and column.
if u find height of image and total rows of original mat both are different,but for perfect place rect they should be same so u have to multiply distance with some constant value to get accurate distance of rect.

Trouble getting the top and bottom of an imageView

I have a simple drawing app where I have a picture of a letter in the back filling an ImageView set to 45% of the screen's height. I have a JSON file that stores points along the letter. I'm trying to display those points on top of the picture of the letter.
Those points' coordinates range between y = -440 and y = 200. In order to properly display the points I need the top and the height of the imageView containing the letter to map the points onto the screen. I have to map the points to the proper points in runtime because with different screen sizes need different scale to display the points properly.
This is what it should look like (this is with a phone specific correction factor):
This is what it actually looks like:
I render the drawing via a Canvas that I paint the points onto. I'm pretty sure the problem lies in how I'm getting the top of the ImageView.
Here's what I've tried:
//1
float y = view.getTop();
//2
final int[] screenPos = new int[2];
iv.getLocationOnScreen(screenPos);
float y = screenPos[1];
//3
float offset = iv.getTop() - screenPos[1];
float y = iv.getTop() + offset;
Is there something I'm supposed to be doing that I'm not? Is there a better way the relative returns of getTop()? Help.
It will give you the position relative to the screen
Rect rect = new Rect();
view.getGlobalVisibleRect(rect);
float top = rect.top;
//there is also rect.bottom, rect.width, rect.height etc.

How can i get the image matrix co ordinates in android?

I am developing an application where is included crop functionality and in this I'm blocked at below scenario.
The scenario:
Crop overlay is not circulating the whole image when we apply straightening to the image if we change the crop overlay, ratio also is not working.
I got the code from google but it is related to matrix, I have tried using matrix, but here I need to find the coordinates(edges) of matrix to move the overlay.
How to find it? If anyone has any idea please help me...
I added the image to explain the problem
Thanks in advance..
I am using the below code but I didn't get the exact coordinates of the matrix
RectF r = new RectF();
mymatrix.mapRect(r);
Rect rect =
new Rect((int)r.left,int)r.top,int)r.right+width,int)r.bottom+height);
You should not use mapRect if you are applying rotation on your matrix. My advice is to figure out the 4 initial points representing each rectangle edge (the image itself) and use mapPoints instead.
Lets say you have an image 200px wide and 200px tall with its top left corner positioned at origin (0,0).
If you rotate this image from its center (100,100) 45 degrees and then scale it 200% from its center we will have the following scenario:
//original image coords
float[] points = {
0f, 0f, //left, top
200f, 0f, //right, top
200f, 200f, //right, bottom
0f, 200f//left, bottom
};
Matrix matrix = new Matrix();
//rotate 45 degrees from image center
matrix.postRotate(45f, 100f, 100f);
//scale 200% from center
matrix.postScale(2f, 2f, 100f, 100f);
//get the new edges coords
matrix.mapPoints(points);
After calling matrix.mapPoints(points) the points array will have the updated coords. This means points[0], points[1] will have the new left top image coord and so on.
The even indices represents the abscissas and the odd indices represents the ordinates on the points array.

How to draw a circle inside a path on canvas in Android

I want to draw a circle inside a path on canvas. To draw a circle, center co-ordinates and radius are required.
How can I calculate the center co-ordinates and radius for a circle inside a path?
The path which you have created might be of irregular shape,it may not contain circle properly,anyways,
You can create a RectF from the Path and then get the center point of the RectF,
RectF mRectF = new RectF();
mOverlayPath.computeBounds(mRectF, true);//here, mOverlayPath is your path
float cX = mRectF.centerX();
float cY = mRectF.centerY();

Using method -canvas.drawBitmap(bitmap, src, dst, paint)

Everytime I use this code nothing is drawn. I need to draw a bitmap inside of a specified rectangle.
canvas.drawBitmap(MyBitmap, null, rectangle, null)
I've looked online but can't find much help.
EDIT
The original answer is incorrect.
You can use the sourceRect to specify a part of a Bitmap to draw.
It may be null, in which case the whole image will be used.
As per the fryer comment he was drawing beneath something, I'll add a note on that.
drawBitmap(bitmap, srcRect, destRect, paint)
does not handle Z ordering (depth) and the order of calling draw on object matters.
If you have 3 shapes to be drawn, square, triangle and circle. If you want the square to be on top then it must be drawn last.
You're not specified any source, so its not drawn anything.
Example:
You have a Bitmap 100x100 pixels. You want to draw the whole Bitmap.
canvas.drawBitmap(MyBitmap, new Rect(0,0,100,100), rectangle, null);
You want to draw only the left half of the bitmap.
canvas.drawBitmap(MyBitmap, new Rect(0,0,50,100), rectangle, null);
You need to specify the source rect, the source rect can be a rectangle anywhere from 0,0 to the width,height of the bitmap.
The main item to remember when defining the Rect is:
left < right and top < bottom
The rect is in screen coordinates (positive Y downward) ...
I find it helpful to think of the Rect arguments
(left, top, right, bottom)
as
(X, Y, X + Width, Y + Height)
where X,Y is the top left corner of the sprite image.
NOTE: If want to center the image on a particular location, remember to offset those values by half the sprite width & height. For example:
int halfWidth = Width/2;
int halfHeight = Height/2
Rect dstRectForRender = new Rect( X - halfWidth, Y - halfHeight, X + halfWidth, Y + halfHeight );
canvas.drawBitmap ( someBitmap, null, dstRectForRender, null );
This uses the whole original image (since src rect is null) and scales it to fit the size and position from dstRectForRender ... and using the default Paint.
I dont know why but this worked for me!
Rect rectangle = new Rect(0,0,100,100);
canvas.drawBitmap(bitmap, null, rectangle, null);
Thanks:)

Categories

Resources