For example I got a picture position in 10,10 with width of 100 and height of 120. I centre rotated it clock-wise 20 degree, the position will be smaller and size will be bigger since the edge will be coming out, but how would I calculate the value for them?
No sure I made the question clear enough, will change it if I find a better way to explain it.
Trying to do this in Android
I assume that you want to know how the bounding box of an object is transformed if you rotate it around its center.
If the original box has width w and height h, the new one, after rotation by r, has dimensions:
wr = abs(sin(r)) * h + abs(cos(r)) * w
hr = abs(sin(r)) * w + abs(cos(r)) * h
Related
I want to find the solution to get the dimensions of an Object Using Camera, Well it sounds like Duplicate one
How to measure height, width and distance of object using camera?
But the solution doesn't help me out.Well from the Above link i got some idea to find out the distance (Measure Distance).
Can somebody suggest me how am i supposed to get the width as well as height of an object. Simple math or any Idea would be really helpful.
Is there any possibilities to achieve the above solution using OpenCV.
Measure Height and Width
What i have tried so far:
Suppose we assume the Fixed Distance , We can calculate Angle of elevation
tan(α/2) = (l/2)/d,
hence
α = 2*atan(l/2d)
But still we don't know the value of L (Length of the object)
Another way to find the View angle:
double thetaV = Math.toRadians(camera.getParameters().getVerticalViewAngle());
double thetaH = Math.toRadians(camera.getParameters().getHorizontalViewAngle());
Seems Not working !!
The actual physics of a lens are explained for example on this website of Georgia State University.
See this illustration which explains how you can use either the linear magnification or focal length relations to find out object size from image size:
In particular, -i / h' = o / h, and this relation o / h holds true for all similar triangles (that is, an object of size 2h at distance 2o has the same sizeh' on the picture). So as you can see, even in the case of the full equation, you can't know both the distance o and the size h of an object -- however one will give you the other.
On the other hand, two objects at the same distance o will see their sizes h1' and h2' on the image be proportional to their sizes in real life h1 and h2, since h1' / h1 = M = h2' / h2.
Hence if you know for one object both oand h, you know M, thus knowing an object's size on film you can deduct its size from its distance and vice versa.
The -i / h' value is naturally expressed for the maximal h'. If the size of an object fills the image exactly, it fills the field of view, then the ratio of its distance to its size is tan(α/2) = (l / 2) / d (note that in the conventions of the image below, d = o and l = 2 * h).
This α is what you name theta in your example. Now, from the image size you can get under what angle you see the image -- that is, what size l would the image be if it were at distance d. From there, you can deduce the size of the object from its distance and vice versa.
Algorithm steps:
get ratio r = size of object in image (in px) / total size of image (in px).
Do this along the axis for which you know or plan to get the real object size, of course.
get the corresponding field of view and angle multiply r by the tangent of half that angle
r *= tan(camera.getParameters().getXXXXViewAngle() / 2)
r is now the tangent of the half-angle under which you see the object, hence the following relations are true: r = (l / 2) / d = h / o (with the respective drawing's notations).
If you know the distance d to the object, its size is l = 2 * r * d
If you know the size l of the object, it is at distance is d = l / (2 * r)
This works for objects hat are actually pointed at by the camera, if they aren't centred the maths may be off.
I have an Image View which displays an image (e.g 2000x1000 pixels) and I have a coordinate (X,Y) on that image (not the image view). The canvas of my Image View is 600x800 for example. How can I convert the point (X,Y) to screen coordinate so that I can draw a path with them on the OnDraw(...) method of Image View. Any help is appreciated! Thank you.
Update: If I use matrix to draw the path between coordinates, it works but the path and objects i draw become really small. Here is the code i used.
final Matrix matrix = canvas.getMatrix();
matrix.preConcat( _view.getImageMatrix() );
matrix.preScale( 1.0f /_inSampleSize, 1.0f / _inSampleSize);
canvas.setMatrix( matrix );
//I draw the path here
Update: I add a picture to show the effect when using matrix to draw the path. I would like to have the 4 line and the 4 corner balls to be in normal size. The red color is the boundary of the Image View which holds the picture.
I think that might depend on how exactly you are displaying your image. Your ImageView (600x800) is not the same aspect ratio as your bitmap (2000x1000).
You are keeping the bitmap's aspect ratio stable as you scale it down? If so, which part (height or width) takes up the full screen and which has black (or whatever else) as padding? This will help you determine your scale factor.
scale_factor = goal_height/height1; //if height is what you are scaling by
scale_factor = goal_width/width1; //if width is what you are scaling by.
I would try:
x_goal = x1 * scale_factor;
y_goal = y1 * scale_factor;
That is, if you have a point (1333, 900) in your image, and your image takes up the full width, you would multiply both x and y by 600/2000 to get (399.9, 270). (you might want to round that decimal).
If you are NOT keeping the bitmaps aspect ratio stable (that is, you're squeezing it to fit), then you'd have a height_scale_factor and a width_scale factor. So you'd take (1333,900) and multiply x by 600/2000 and y by 800/1000 to get (399.9,720).
I'm hoping someone can help me out. I'm making an image manipulation app, and I found I needed a better way to load in large images.
My plan, is to iterate through "hypothetical" pixels of an image (a "for loop" that covers width/height of the base image, so each iteration represents a pixel), scale/translate/rotate that pixels position relative to the view, then use this information to determine which pixels are being displayed in the view itself, then use a combination of BitmapRegionDecoder and BitmapFactory.Options to load in only the section of image that the output actually needs rather than a full (even if scaled) image.
So far I seem to have covered scale of the image and translation properly, but I can't seem to figure out how to calculate rotation. Since it's not a real Bitmap pixel I can't use Matrix.rotate =( Here is the image translations in the onDraw of the view, imgPosX and imgPosY hold the center point of the image:
m.setTranslate(-userImage.getWidth() / 2.0f, -userImage.getHeight() / 2.0f);
m.postScale(curScale, curScale);
m.postRotate(angle);
m.postTranslate(imgPosX, imgPosY);
mCanvas.drawBitmap(userImage.get(), m, paint);
and here is the math so far of how I'm trying to determine if an images pixel is on the screen:
for(int j = 0;j < imageHeight;j++) {
for(int i = 0;i < imageWidth;i++) {
//image starts completely center in view, assume image is original size for simplicity
//this is the original starting position for each pixel
int x = Math.round(((float) viewSizeWidth / 2.0f) - ((float) newImageWidth / 2.0f) + i);
int y = Math.round(((float) viewSizeHeight / 2.0f) - ((float) newImageHeight / 2.0f) + j);
//first we scale the pixel here, easy operation
x = Math.round(x * imageScale);
y = Math.round(y * imageScale);
//now we translate, we do this by determining how many pixels
//our images x/y coordinates have differed from it's original
//starting point, imgPosX and imgPosY in the view start in center
//of view
x = x + Math.round((imgPosX - ((float) viewSizeWidth / 2.0f)));
y = y + Math.round((imgPosY - ((float) viewSizeHeight / 2.0f)));
//TODO need rotation here
}
}
so, assuming my math up until rotation is correct (probably not but it appears to be working so far), how would I then calculate the rotation from that pixels position? I've tried other similar questions like:
Link 1
Link 2
Link 3
without using rotation the pixels I expect to actually be on the screen are represented (I made text file that outputs the results in 1's and 0's so I can have a visual representation of whats on the screen), but with the formula found in those questions the information isn't what is expected. (Scenario: I've rotated an image so only the top left corner is visible in the view. Using the info from Here to rotate the pixel, I should expect to see a triangular set of 1's in the upper left corner of the output file, but that's not the case)
So, how would I calculate a a pixels position after rotation without using the Android matrix? But still get the same results.
And if I've just messed it up entirely my apologies =( Any help would be appreciated, this project has gone on for so long and I want to finally be done lol
If you need any more information I will provide as much as I possibly can =) Thank you for your time
I realize this question is particularly difficult so I will be posting a bounty as soon as SO allows.
You do not need to create your own Matrix, use the existing one.
http://developer.android.com/reference/android/graphics/Matrix.html
You can map bitmap coordinates to screen coordinates by using
float[] coords = {x, y};
m.mapPoints(coords);
float sx = coords[0];
float sy = coords[1];
If you want to map screen to bitmap coordinates, you can create the inverse matrix
Matrix inverse = new Matrix(m);
inverse.inverse();
inverse.mapPoints(...)
I think your overall approach is going to be slow, as doing the pixel manipulation on the CU from Java has a lot of overhead. When drawing bitmaps normally, the pixel manipulation is done on the GPU.
I want to calculate rotated image size, Image is inside rectangle. I have rectangle width, height and angle of rotated image. Any one tell me
how to calculate rotated image size?
So you have width, height and angle means you already got RotatedRect.
Now using the method
Rect RotatedRect::boundingRect();
you can easly calculate the bounding box for rotated rect.
for more info see RotatedRect.
Edit:
As per your comment below is the way how to find the width and height of rotated rect.
So you know the four corners of rectangle, lets say (x1,y1),(x2,y2),(x3,y3),(x4,y4), now you need to find the transformed point after rotation by the given angle, let it be (xT1,yT1),(xT2,yT2),etc...
where
xT = x0+(x-x0)*cos(theta)+(y-y0)*sin(theta)
yT = y0-(x-x0)*sin(theta)+(y-y0)*cos(theta)
here (x0,y0) is the center around which you are rotating. and theta = angle * CV_PI / 180.0
Using above calculate four transformed points, finally calculate the height and width by finding the distance between transformed points.
My app that I am trying to create is a board game. It will have one bitmap as the board and pieces that will move to different locations on the board. The general design of the board is square, has a certain number of columns and rows and has a border for looks. Think of a chess board or scrabble board.
Before using bitmaps, I first created the board and boarder by manually drawing it - drawLine & drawRect. I decided how many pixels in width the border would be based on the screen width and height passed in on "onSizeChanged". The remaining screen I divided by the number of columns or rows I needed.
For examples sake, let's say the screen dimensions are 102 x 102.
I may have chosen to set the border at 1 and set the number of rows & columns at 10. That would leave 100 x 100 left (reduced by two to account for the top & bottom border, as well as left/right border). Then with columns and rows set to 10, that would leave 10 pixels left for both height and width.
No matter what screen size is passed in, I store exactly how many pixels in width the boarder is and the height & width of each square on the board. I know exactly what location on the screen to move the pieces to based on a simple formula and I know exactly what cell a user touched to make a move.
Now how does that work with bitmaps? Meaning, if I create 3 different background bitmaps, once for each density, won't they still be resized to fit each devices screen resolution, because from what I read there were not just 3 screen resolutions, but 5 and now with tablets - even more. If I or Android scales the bitmaps up or down to fit the current devices screen size, how will I know how wide the border is scaled to and the dimensions of each square in order to figure out where to move a piece or calculate where a player touched. So far the examples I have looked at just show how to scale the overall bitmap and get the overall bitmaps width and height. But, I don't see how to tell how many pixels wide or tall each part of the board would be after it was scaled. When I draw each line and rectangle myself based in the screen dimensions from onSizeChanged, I always know these dimensions.
If anyone has any sample code or a URL to point me to that I can a read about this with bitmaps, I would appreciate it.
BTW, here is some sample code (very simplified) on how I know the dimensions of my game board (border and squares) no matter the screen size. Now I just need to know how to do this with the board as a bitmap that gets scaled to any screen size.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
intScreenWidth = w;
intScreenHeight = h;
// Set Border width - my real code changes this value based on the dimensions of w
// and h that are passed in. In other words bigger screens get a slightly larger
// border.
intOuterBorder = 1;
/** Reserve part of the board for the boardgame and part for player controls & score
My real code forces this to be square, but this is good enough to get the point
across.
**/
floatBoardHeight = intScreenHeight / 4 * 3;
// My real code actually causes floatCellWidth and floatCellHeight to
// be equal (Square).
floatCellWidth = (intScreenWidth - intOuterBorder * 2 ) / intNumColumns;
floatCellHeight = (floatBoardHeight - intOuterBorder * 2) / intNumRows;
super.onSizeChanged(w, h, oldw, oldh);
}
I think I found the answer. I might not be able to find the exact width/height and location of each playable square within a single scaled bitmap, but by looking at the Snake example in the SDK, I see it doesn't create 1 bitmap for the entire board and scale it based on the screen dimensions - instead it creates a bitmap for each tile and then scales the tile based on the screen resolution and the number of tiles wanted on the screen - just like I do when I draw the board manually. With this method, I should be able find the exact pixel boundaries for all of the playable squares on the board. I just have to break the board into multiple bitmaps for each square. I probably will have to do a similar approach for the borders, so I can detect their width/height as well after scaling.
Now I will test it to verify, but I expect it to work based on what I saw in the Snake SDK example.
--Mike
I tested a way to do what I was asking and it seems to work. Here is what I did:
I created a 320 x 320 bitmap for a board. It was made up of a border and squares (like a chess board). The border was 10 pixels in width all the way around the board. The squares were 20 x 20 pixels.
I detected the width and height of the screen through onSizeChanged. On a 480 x 800 display, I would set the new width for the board to be 480 x 480 and use the following code to scale the whole thing:
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
floatBoardWidth = w;
floatBoardHeight = floatBoardWidth;
bitmapScaledBoard = Bitmap.createScaledBitmap(bitmapBoard, (int)floatBoardWidth, (int)floatBoardHeight, true);
super.onSizeChanged(w, h, oldw, oldh);
}
Now in order to detect how many pixels wide the border was scaled to and how many pixels in height & width the squares were scaled to, I first calculated how much the over all image was scaled. I knew the bitmap was 320 x 320, since I created it. I used the following formula to calculate how much the image was scaled:
floatBoardScale = floatScreenWidth / 320;
In the case of a 480 width screen, floatBoardScale equals: 1.5. Then to calculate what my border within the full bitmap was scaled to, I did:
floatBorderWidth = 10 * floatBoardScale;
10 was the original border width in my 320 x 320 bitmap. In my final code I won't hardcode values, I will use variables. Anyway, in the case of this formula, the new calculated border width should be: 15
When I multiplied the same scale factor to the board squares (that were 20 x 20 in the original bitmap) I got new values of 30 x 30. When I used those values in my formulas to calculate what square a person touched, it worked. I touched every corner of the squares and in the center and it always calculated the right location. Which is important, so no matter what the screen resolution, I know where the user wanted to move a piece and visually it shows up in the right location.
I hope this helps anyone who may have had the same question. Also, if anyone has a better method of accomplishing the same thing, please post it.
A couple things. First, start reading about how to support multiple screens. Pay close attention to learning about dips and how they work.
Next, watch this video (at least the first 15-20 minutes of it).
This subject isn't a cakewalk to grasp. I found it best to start playing around inside my code. I would suggest creating a surfaceview and start messing around with some bitmaps, different emulators (screen sizes and densities), and the different types of drawable folders.
Unfortunately, there is more to this topic than I think Google wants to admit, and while it's definitely do-able is isn't simple to get started on it for some types of applications.
Finally, you should consider boiling down your question to be more straight forward if you aren't looking for an abstract answer (like this one).
Good luck!