Related
A similar question was asked before, unfortunately I cannot comment Samgaks answer so I open up a new post with this one. Here is the link to the old question:
How to calculate ray in real-world coordinate system from image using projection matrix?
My goal is to map from image coordinates to world coordinates. In fact I am trying to do this with the Camera Intrinsics Parameters of the HoloLens Camera.
Of course this mapping will only give me a ray connecting the Camera Optical Centre and all points, which can lie on that ray. For the mapping from image coordinates to world coordinates we can use the inverse camera matrix which is:
K^-1 = [1/fx 0 -cx/fx; 0 1/fy -cy/fy; 0 0 1]
Pcam = K^-1 * Ppix;
Pcam_x = P_pix_x/fx - cx/fx;
Pcam_y = P_pix_y/fy - cy/fy;
Pcam_z = 1
Orientation of Camera Coordinate System and Image Plane
In this specific case the image plane is probably at Z = -1 (However, I am a bit uncertain about this). The Section Pixel to Application-specified Coordinate System on page HoloLens CameraProjectionTransform describes how to go form pixel coordinates to world coordinates. To what I understand two signs in the K^-1 are flipped s.t. we calculate the coordinates as follows:
Pcam_x = (Ppix_x/fx) - (cx*(-1)/fx) = P_pix_x/fx + cx/fx;
Pcam_y = (Ppix_y/fy) - (cy*(-1)/fy) = P_pix_y/fy + cy/fy;
Pcam_z = -1
Pcam = (Pcam_x, Pcam_y, -1)
CameraOpticalCentre = (0,0,0)
Ray = Pcam - CameraOpticalCentre
I do not understand how to create the Camera Intrinsics for the case of the image plane being at a negative Z-coordinate. And I would like to have a mathematical explanation or intuitive understanding of why we have the sign flip (P_pix_x/fx + cx/fx instead of P_pix_x/fx - cx/fx).
Edit: I read in another post that the thirst column of the camera matrix has to be negated for the case that the camera is facing down the negative z-direction. This would explain the sign flip. However, why do we need to change the sign of the third column. I would like to have a intuitive understanding of this.
Here the link to the post Negation of third column
Thanks a lot in advance,
Lisa
why do we need to change the sign of the third column
To understand why we need to negate the third column of K (i.e. negate the principal points of the intrinsic matrix) let's first understand how to get the pixel coordinates of a 3D point already in the camera coordinates frame. After that, it is easier to understand why -z requires negating things.
let's imagine a Camera c, and one point B in the space (w.r.t. the camera coordinate frame), let's put the camera sensor (i.e. image) at E' as in the image below. Therefore f (in red) will be the focal length and ? (in blue) will be the x coordinate in pixels of B (from the center of the image). To simplify things let's place B at the corner of the field of view (i.e. in the corner of the image)
We need to calculate the coordinates of B projected into the sensor d (which is the same as the 2d image). Because the triangles AEB and AE'B' are similar triangles then ?/f = X/Z therefore ? = X*f/Z. X*f is the first operation of the K matrix is. We can multiply K*B (with B as a column vector) to check.
This will give us coordinates in pixels w.r.t. the center of the image. Let's imagine the image is size 480x480. Therefore B' will look like this in the image below. Keep in mind that in image coordinates, the y-axis increases going down and the x-axis increases going right.
In images, the pixel at coordinates 0,0 is in the top left corner, therefore we need to add half of the width of the image to the point we have. then px = X*f/Z + cx. Where cx is the principal point in the x-axis, usually W/2. px = X*f/Z + cx is exactly as doing K * B / Z. So X*f/Z was -240, if we add cx (W/2 = 480/2 = 240) and therefore X*f/Z + cx = 0, same with the Y. The final pixel coordinates in the image are 0,0 (i.e. top left corner)
Now in the case where we use z as negative, when we divide X and Y by Z, because Z is negative, it will change the sign of X and Y, therefore it will be projected to B'' at the opposite quadrant as in the image below.
Now the second image will instead be:
Because of this, instead of adding the principal point, we need to subtract it. That is the same as negating the last column of K.
So we have 240 - 240 = 0 (where the second 240 is the principal point in x, cx) and the same for Y. The pixel coordinates are 0,0 as in the example when z was positive. If we do not negate the last column we will end up with 480,480 instead of 0,0.
Hope this helped a little bit
I have some damaged line segments in a binary image and I need to fix them (make them straight and at their original thick). In order to do that I have to find the middle points of the segment, so when I check the neighborhood to find the thickness of the lines I'll be able to find where the pixel stops being 1 and becomes 0.
Assuming your damaged line segments are straight, you can use regionprops in MATLAB to find the center of each bounding box. Because if a segment is straight, its is always the diagonal line of the bounding box, thus the center of the box is also the center of the semgent.
Let's call the points A and B to reduce ambiguity, A(Xa, Ya) and B(Xb, Yb)
Let C be the middle point.
C(Xc, Yc)
Xc = (Xa + Xb) / 2
Yc = (Ya + Yb) / 2
We have four interesting numbers, two for the X coordinates and two for the Y coordinates.
Xmin = floor(Xc)
Xmax = ceil(Xc)
Ymin = floor(Yc)
Ymax = ceil(Yc)
The X coordinate of your middle point is either Xmin or Xmax, the Y coordinate of your middle point is either Ymin or Ymax.
So we have four potential points: (Xmin, Ymin), (Xmin, Ymax), (Xmax, Ymin), (Xmax, Ymax).
So, finally, we must decide which point is nearest to C.
Distance from P(Xp, Yp) to C(Xc, Yc) is:
sqrt(sqr(Xp - Xc) + sqr(Yp - Yc))
Calculate the four distance from the four points to C, choose the minimum and that will be the best possible middle point.
Suppose
A = [xa ya];
B = [xb yb];
then
C = round( mean([A;B]) );
Matlab's round rounds numbers towards their nearest integer, so this minimizes the (city-block) distance from the analytical center (mean([A;B])) to the nearest pixel.
If you want to keep sub-pixel precision (which is actually advisable for most calculations until an explicit map from a result to pixel indices is required), just drop the round and use only the mean part.
I've had this problem for a few years. It was on an informatics contest in my town a while back. I failed to solve it, and my teacher failed to solve it. I haven't met anyone who was able to solve it. Nobody I know knows the right way to give the answer, so I decided to post it here:
Ze problem
Given a rectangle, X by Y, find the minimum amount of circles N with a fixed given radius R, necessary to fully cover every part of the rectangle.
I have thought of ways to solve it, but I have nothing definite. If each circle defines an inner rectangle, then R^2 = Wi^2 + Hi^2, where Wi and Hi are the width and height of the practical area covered by each circle i. At first I thought I should make Wi equal to Wj for any i=j, the same for H. That way, I could simplify the problem by making the width/height ratios equal with the main rectangle (Wi/Hi = X/Y). That way, N=X/Wi. But that solution is surely wrong in case X greatly exceeds Y or vice versa.
The second idea was that Wi=Hi for any given i. That way, squares fill space most efficiently. However if a very narrow strip remains, it's much more optimal to use rectangles to fill it, or better yet - use rectangles for the last row before that too.
Then I realized that none of the ideas are the optimal, since I can always find better ways of doing it. It will always be close to final, but not final.
Edit
In some cases (large rectangle) joining hexagons seem to be a better solution than joining squares.
Further Edit
Here's a comparison of 2 methods: clover vs hexagonal. Hexagonal is, obviously, better, for large surfaces. I do think however that when the rectangle is small enough, rectangular method may be more efficient. It's a hunch. Now, in the picture you see 14 circles on the left, and 13 circles on the right. Though the surface differs much greater (double) than one circle. It's because on the left they overlap less, thus waste less surface.
The questions still remain:
Is the regular hexagon pattern itself optimal? Or certain adjustments should be made in parts of the main rectangle.
Are there reasons not to use regular shapes as "ultimate solution"?
Does this question even have an answer? :)
For X and Y large compared to R, a hexagonal (honeycomb) pattern is near optimal. The distance between the centers of the circles in the X-direction is sqrt(3)*R. The distance between rows in the Y-direction is 3*R/2, so you need roughly X*Y/R^2 * 2*/(3*sqrt(3)) circles.
If you use a square pattern, the horizontal distance is larger (2*R), but the vertical distance is much smaller (R), so you'd need about X*Y/R^2 * 1/2 circles. Since 2/(3*sqrt(3) < 1/2, the hexagonal pattern is the better deal.
Note that this is only an approximation. It is usually possible to jiggle the regular pattern a bit to make something fit where the standard pattern wouldn't. This is especially true if X and Y are small compared to R.
In terms of your specific questions:
The hexagonal pattern is an optimal covering of the entire plane. With X and Y finite, I would think it is often possible to get a better result. The trivial example is when the height is less than the radius. In that case you can move the circles in the one row further apart until the distance between the intersecting points of every pair of circles equals Y.
Having a regular pattern imposes additional restrictions on the solution, and so the optimal solution under those restrictions may not be optimal with those restrictions removed. In general, somewhat irregular patterns may be better (see the page linked to by mbeckish).
The examples on that same page are all specific solutions. The solutions with more circles resemble the hexagonal pattern somewhat. Still, there does not appear to be a closed-form solution.
This site attacks the problem from a slightly different angle: Given n unit circles, what is the largest square they can cover?
As you can see, as the number of circles changes, so does the covering pattern.
For your problem, I believe this implies: different rectangle dimensions and circle sizes will dictate different optimal covering patterns.
The hexagon is better than the diamond. Consider the percent area of the unit circle covered by each:
#!/usr/bin/env ruby
include Math
def diamond
# The distance from the center to a corner is the radius.
# On a unit circle, that is 1.
radius = 1
# The edge of the nested diamond is the hypotenuse of a
# right triangle whose legs are both radii.
edge = sqrt(radius ** 2 + radius ** 2)
# The area of the diamond is the square of the edge
edge ** 2
end
def hexagon
# The hexagon is composed of 6 equilateral triangles.
# Since the inner edges go from the center to a hexagon
# corner, their length is the radius (1).
radius = 1
# The base and height of an equilateral triangle whose
# edge is 'radius'.
base = radius
height = sin(PI / 3) * radius
# The area of said triangle
triangle_area = 0.5 * base * height
# The area of the hexagon is 6 such triangles
triangle_area * 6
end
def circle
radius = 1
PI * radius ** 2
end
puts "diamond == #{sprintf "%2.2f", (100 * diamond / circle)}%"
puts "hexagon == #{sprintf "%2.2f", (100 * hexagon / circle)}%"
And
$ ./geometrons.rb
diamond == 63.66%
hexagon == 82.70%
Further, regular hexagons are highest-vertex polygon that form a regular tessellation of the plane.
According my calculations the right answer is:
D=2*R; X >= 2*D, Y >= 2*D,
N = ceil(X/D) + ceil(Y/D) + 2*ceil(X/D)*ceil(Y/D)
In particular case if the remainder for X/D and Y/D equal to 0, then
N = (X + Y + X*Y/R)/D
Case 1: R = 1, X = 2, Y = 2, then N = 4
Case 2: R = 1, X = 4, Y = 6, then N = 17
Case 3: R = 1, X = 5, Y = 7, then N = 31
Hope it helps.
When the circles are disposed as a clover with four leafs with a fifth circle in the middle, a circle will cover an area equal to R * 2 * R. In this arrangement, the question becomes: how many circles that cover an area of R * 2 * R will cover an area of W * H?, or N * R * 2 * R = W * H. So N = W * H / R * 2 * R.
Given n squares with edge length l, how can I determine the minimum radius r of the circle so that I can distribute all squares evenly along the perimeter of the circle without them overlapping? (Constraint: the first square will always be positioned at 12 o'clock.)
Followup question: how can I place n identical rectangles with height h and width w?
(source: n3rd.org)
There may be a mathematically clever way to do this, but I wouldn't know.
I think it's complicated a bit by the fact that the geometry is different for every different number of squares; for 4 it's a rhombus, for 5 it's a pentagon and so on.
What I'd do is place those squares on a 1 unit circle (much too small, I know, bear with me) distributed equally on it. That's easy enough, just subtend (divide) your 360 degrees by the number of squares. Then just test all your squares for overlap against their neighbors; if they overlap, increase the radius.
You can make this procedure less stupid than it sounds by using an intelligent algorithm to approach the right size. I'm thinking of something like Newton's algorithm: Given two successive guesses, of which one is too small and one is too big, your next guess needs to be the average of those two.
You can iterate down to any precision you like. Stop whenever the distance between guesses is smaller than some arbitrary small margin of error.
EDIT I have a better solution:
I was thinking about what to tell you if you asked "how will I know if squares overlap?" This gave me an idea on how to calculate the circle size exactly, in one step:
Place your squares on a much-too-small circle. You know how: Calculate the points on the circle where your 360/n angles intersect it, and put the center of the square there. Actually, you don't need to place squares yet, the next steps only require midpoints.
To calculate the minimum distance of a square to its neighbor: Calculate the difference in X and the difference in Y of the midpoints, and take the minimum of those. The X's and Y's are actually just cosines and sines on the circle.
You'll want the minimum of any square against its neighbor (clockwise, say). So you need to work your way around the circle to find the very smallest one.
The minimum (X or Y) distance between the squares needs to become 1.0 . So just take the reciprocal of the minimum distance and multiply the circle's size by that. Presto, your circle is the right size.
EDIT
Without losing generality, I think it's possible to nail my solution down a bit so it's close to coding. Here's a refinement:
Assume the squares have size 1, i.e. each side has a length of 1 unit. In the end, your boxes will surely be larger than 1 pixel but it's just a matter of scaling.
Get rid of the corner cases:
if (n < 2) throw new IllegalArgumentException();
if (n == 2) return 0.5; // 2 squares will fit exactly on a circle of radius 0.5
Start with a circle size r of 0.5, which will surely be too small for any number of squares > 2.
r = 0.5;
dmin = 1.0; // start assuming minimum distance is fine
a = 2 * PI / n;
for (p1 = 0.0; p1 <= PI; p1+=a) { // starting with angle 0, try all points till halfway around
// (yeah, we're starting east, not north. doesn't matter)
p2 = p1 + a; // next point on the circle
dx = abs(r * cos(p2) - r * cos(p1))
dy = abs(r * sin(p2) - r * sin(p1))
dmin = min(dmin, dx, dy)
}
r = r / dmin;
EDIT
I turned this into real Java code and got something quite similar to this to run. Code and results here: http://ideone.com/r9aiu
I created graphical output using GnuPlot. I was able to create simple diagrams of boxes arranged in a circle by cut-and-pasting the point sets from the output into a data file and then running
plot '5.dat' with boxxyerrorbars
The .5's in the file serve to size the boxes... lazy but working solution. The .5 is applied to both sides of the center, so the boxes end up being exactly 1.0 in size.
Alas, my algorithm doesn't work. It makes the radii far too large, thus placing the boxes much further apart than necessary. Even scaling down by a factor of 2 (could have been a mistake to use 0.5 in some places) didn't help.
Sorry, I give up. Maybe my approach can be salvaged, but it doesn't work the way I had though it would. :(
EDIT
I hate giving up. I was about to leave my PC when I thought of a way to salvage my algorithm:
The algorithm was adjusting the smaller of the X or Y distances to be at least 1. It's easy to demonstrate that's just plain silly. When you have a lot of boxes then at the eastern and western edges of the circle you have boxes stacked almost directly on top of each other, with their X's very close to one another but they are saved from touching by having just enough Y distance between them.
So... to make this work, you must scale the maximum of dx and dy to be (for all cases) at least the radius (or was it double the radius?).
Corrected code is here: http://ideone.com/EQ03g http://ideone.com/VRyyo
Tested again in GnuPlot, it produces beautiful little circles of boxes where sometimes just 1 or 2 boxes are exactly touching. Problem solved! :)
(These images are wider than they are tall because GnuPlot didn't know I wanted proportional layout. Just imagine the whole works squeezed into a square shape :) )
I would calculate an upper bound of the minimum radius, by working with circles enclosing the squares instead of with the squares themselves.
My calculation results in:
Rmin <= X / (sqrt(2) * sin (180/N) )
Where:
X is the square side length, and N is the required number of squares.
I assume that the circles are positioned such that their centers fall on the big circle's circumference.
-- EDIT --
Using the idea of Dave in the comment below, we can also calculate a nice lower bound, by considering the circles to be inside the squares (thus having radius X/2). This bound is:
Rmin >= X / (2 * sin (180/N) )
As already noted, the problem of positioning n points equally spaced round the circumference of a circle is trivial. The (not-terribly) difficult part of the problem is to figure out the radius of the circle needed to give a pleasing layout of the squares. I suggest you follow one of the other answers and think of the squares being inside a circular 'buffer' big enough to contain the square and enough space to satisfy your aesthetic requirements. Then check the formula for the chord length between the centres of neighbouring squares. Now you have the angle, at the centre of the circle, subtended by the chord between square centres, and can easily compute the radius of the circle from the trigonometry of a triangle.
And, as to your follow up question: I suggest that you work out the problem for squares of side length min(h,w) on a circle, then transform the squares to rectangles and the circle to an ellipse with eccentricity h/w (or w/h).
I would solve it like this:
To find the relation between the radius r and length l let's analyze dimensionless representation
get the centres on a circle (x1,y1)..(xn,yn)
from each center get lower right corner of the i-th square and upper left corner of the i+1-th square
the two points should either have equal x or equal y, whichever yields smaller l
procedure should be repeated for each center and the one that yields smallest l is the final solution.
This is the optimal solution and can be solved it terms of r = f(l).
The solution can be adapted to rectangles by adjusting the formula for xLR[i] and yUL[i+1].
Will try to give some pseudo code.
EDIT:
There's a bug in the procedure, lower right and upper left are not necessary closest points for two neighbouring squares/rectangles.
Let's assume you solved the problem for 3 or 4 squares.
If you have n >= 5 squares, and position one square at the top of the circle, you'll have another square fall into the first quadrant of a cartesian plane concentric with your circle.
The problem is then to find a radius r for the circle such that the left side of the circle next to the top one, and the right side of the top circle do not 'cross' each other.
The x coordinate of the right side of the top circle is x1 = L/2, where L is the side of a square. The x coordinate of the left side of the circle next to the top one is x2 = r cos a - L/2, where r is the radius and a is the angle between each pair of square centres (a = 360/n degrees).
So we need to solve x1 <= x2, which leads to
r >= L / cos a.
L and a are known, so we're done :-)
You start with an arbitrary circle (e.g., with a diameter of (* n l)) and position the squares evenly on the circumference. Then you go through each pair of adjacent squares and:
calculate the straight line connecting their mid points,
calculate the intersection of this line with the intervening square sides (M1 and M2 are the mid points, S1 and S2 the corresponding intersections with the square side:
S2 S1
M1--------------*----------*---------------M2
------------------------
| |
| |
| |
| |
| M1 |
| \ |
| \ |
| -------*------- +--------
| | \ | |
| | \ | |
-------+---------*------ |
| \ |
| M2 |
| |
| |
| |
| |
-------------------------
calculate the scale factor you would need to make S1 and S2 fall together (simply the ratio of the sum of M1-S1 and S2-M2 to M1-M2), and
finally scale the circle by the maximum of the found scale factors.
Edit: This is the exact solution. However, a little thought can optimize this further for speed:
You only need to do this for the squares closest to 45° (if n is even) resp. 45° and 135° (if n is odd; actually, you might prove that only one of these is necessary).
For large n, the optimal spacing of the squares on the circle will quickly approach the length of a diagonal of a square. You could thus precompute the scaling factors for a few small n (up to a dozen or so), and then have a good enough approximation with the diagonal.
I have the need to determine the bounding rectangle for a polygon at an arbitrary angle. This picture illustrates what I need to do:
alt text http://kevlar.net/RotatedBoundingRectangle.png
The pink rectangle is what I need to determine at various angles for simple 2d polygons.
Any solutions are much appreciated!
Edit:
Thanks for the answers, I got it working once I got the center points correct. You guys are awesome!
To get a bounding box with a certain angle, rotate the polygon the other way round by that angle. Then you can use the min/max x/y coordinates to get a simple bounding box and rotate that by the angle to get your final result.
From your comment it seems you have problems with getting the center point of the polygon. The center of a polygon should be the average of the coordinate sums of each point. So for points P1,...,PN, calculate:
xsum = p1.x + ... + pn.x;
ysum = p1.y + ... + pn.y;
xcenter = xsum / n;
ycenter = ysum / n;
To make this complete, I also add some formulas for the rotation involved. To rotate a point (x,y) around a center point (cx, cy), do the following:
// Translate center to (0,0)
xt = x - cx;
yt = y - cy;
// Rotate by angle alpha (make sure to convert alpha to radians if needed)
xr = xt * cos(alpha) - yt * sin(alpha);
yr = xt * sin(alpha) + yt * cos(alpha);
// Translate back to (cx, cy)
result.x = xr + cx;
result.y = yr + cx;
To get the smallest rectangle you should get the right angle. This can acomplished by an algorithm used in collision detection: oriented bounding boxes.
The basic steps:
Get all vertices cordinates
Build a covariance matrix
Find the eigenvalues
Project all the vertices in the eigenvalue space
Find max and min in every eigenvalue space.
For more information just google OBB "colision detection"
Ps: If you just project all vertices and find maximum and minimum you're making AABB (axis aligned bounding box). Its easier and requires less computational effort, but doesn't guarantee the minimum box.
I'm interpreting your question to mean "For a given 2D polygon, how do you calculate the position of a bounding rectangle for which the angle of orientation is predetermined?"
And I would do it by rotating the polygon against the angle of orientation, then use a simple search for its maximum and minimum points in the two cardinal directions using whatever search algorithm is appropriate for the structure the points of the polygon are stored in. (Simply put, you need to find the highest and lowest X values, and highest and lowest Y values.)
Then the minima and maxima define your rectangle.
You can do the same thing without rotating the polygon first, but your search for minimum and maximum points has to be more sophisticated.
To get a rectangle with minimal area enclosing a polygon, you can use a rotating calipers algorithm.
The key insight is that (unlike in your sample image, so I assume you don't actually require minimal area?), any such minimal rectangle is collinear with at least one edge of (the convex hull of) the polygon.
Here is a python implementation for the answer by #schnaader.
Given a pointset with coordinates x and y and the degree of the rectangle to bound those points, the function returns a point set with the four corners (and a repetition of the first corner).
def BoundingRectangleAnglePoints(x,y, alphadeg):
#convert to radians and reverse direction
alpha = np.radians(alphadeg)
#calculate center
cx = np.mean(x)
cy = np.mean(y)
#Translate center to (0,0)
xt = x - cx
yt = y - cy
#Rotate by angle alpha (make sure to convert alpha to radians if needed)
xr = xt * np.cos(alpha) - yt * np.sin(alpha)
yr = xt * np.sin(alpha) + yt * np.cos(alpha)
#Find the min and max in rotated space
minx_r = np.min(xr)
miny_r = np.min(yr)
maxx_r = np.max(xr)
maxy_r = np.max(yr)
#Set up the minimum and maximum points of the bounding rectangle
xbound_r = np.asarray([minx_r, minx_r, maxx_r, maxx_r,minx_r])
ybound_r = np.asarray([miny_r, maxy_r, maxy_r, miny_r,miny_r])
#Rotate and Translate back to (cx, cy)
xbound = (xbound_r * np.cos(-alpha) - ybound_r * np.sin(-alpha))+cx
ybound = (xbound_r * np.sin(-alpha) + ybound_r * np.cos(-alpha))+cy
return xbound, ybound