i have a 3d model in a coordinate system that i need to project on a 2d plane using perspective projection, i used this projection equation C*(RT * P') where C is the calibration matrix
[f 0 px
0 f py
0 0 1]
px and py are coordinates of origin point i put them both by zero, R is the rotation matrix and T is the translation matrix i put them both in one matrix that represent both of them and i used a translation value of 3meters (in pixel value : 9448.82 approximately , not sure if this conversion is right) on Z-axis and 1 meter on Y axis, f is the focal length and i'm not sure of the value i used but i calculated it by this equation:
f= (image width) * (image focal length) / (7.81) , i got the 7.81 value from my camera brand website as it is supposed to be an internal camera parameter and this is what i'm not sure if it is right.
this is a screenshot of the model that i'm trying to project.
and this is the model after projection ... it seems to me like it is scaled over X axis it doesn't feel like it's exactly the same model and after filling the gaps between the points by some filling algorithm :
here is the result it is more unlike the original model ... any help please about where the problem is so i can fix it .. thanks :)
Related
I'm having a bit of trouble understanding how axis-angle rotation vectors are used when rotating a vector in 3D space. Why are these used and how do these relate to rotation matrices?
I also found a function called vrrotvec2mat that seems to do what I want but I can't understand the documentation. Specifically, can someone give a more clear explanation (with some example) of the input arguments r and options?
MathWorks explanations are very limited, as follows:
Convert rotation from axis-angle to matrix representation
m = vrrotvec2mat(r) returns a matrix representation of the rotation defined by the axis-angle rotation vector, r.
m = vrrotvec2mat(r,options) returns a matrix representation of rotation defined by the axis-angle rotation vector r, with the default algorithm parameters replaced by values defined in options.
The options structure contains the parameter epsilon that represents the value below which a number will be treated as zero (default value is 1e-12).
The rotation vector, r, is a row vector of four elements, where the first three elements specify the rotation axis, and the last element defines the angle.
To rotate a column vector of three elements, multiply it by the rotation matrix. >To rotate a row vector of three elements, multiply it by the transposed rotation matrix.
If you want to understand the vrrotvec2mat function, you need to know how axis-angle representations of rotations work before we delve into this function. Specifically, you're looking at understanding the Rodrigues Rotation formula, which is also known as the axis-angle rotation formula. I'll explain this to you with some introduction first.
In Linear Algebra, the most standard way to rotate a point, whether it's 2D or 3D is to use a rotation matrix where you pre-multiply (i.e. y = A*x where x is your point represented in a column vector) the 2D or 3D coordinate with this rotation matrix. This rotates the point around the origin of the coordinate system. You can also think of this as rotating a vector v where the tail is at the origin and the head is at the point in 2D or 3D space.
However, another way to do this is to provide what is known as the axis-angle representation which is only valid in 3D space. The axis is described by a unit vector k that describes an axis of rotation about which the vector v rotates by an angle around this axis by the right-hand rule.
Here's a pictorial example I got from Wikipedia:
Source: Rodrigues' Rotation formula
The vector k in our case is pointing straight up and the vector v is pointing on a 45 degree angle northwest. We wish to rotate this vector by an angle of 180 degrees around the axis defined by the vector k, and so if you do this, vrot is the resulting vector. v|| and v_|_ are the parallel and perpendicular projections of v with respect to the vector k. These are shown to derive the Rodrigues formula, which I won't go through here. I'll refer you to the article if you want a full derivation.
The reason why the Rodrigues rotation formula was proposed to rotate things is because very frequently, there are applications where you are rotating about an axis that is not centred at the origin, nor are you rotating with respect to a standard x,y and z axis.
In fact, if you look at the Wikipedia article, you don't need to convert to the matrix form to rotate things. You can use the unit vector and rotation angle directly to rotate your vector, which leads us to his rotation formula:
Source: Rodrigues' Rotation formula
The reason why vrrotvec2mat exists is because you can convert between the axis-angle representation of rotating a vector and a rotation matrix with a rotation with respect to the origin in Linear Algebra. You can then apply the same Linear Algebra theory to rotate a vector/point in 3D space given this rotation matrix. You can convert back and forth between a normal rotation matrix and the Rodrigues formula representation by using vrrotvec2mat and vrrotmat2vec respectively.
The axis-angle representation is essentially a 4 element vector where the first three elements are the x,y and z components of the unit vector k that defines your rotation axis and the last element is the rotation angle theta that rotates your vector with respect to this axis. vrrotvec2mat is no different here and requires a 4 element vector in the order that I just talked about. However, having a quick look at the source, theta is defined in radians.
If you want a concrete example of seeing this work, let's use the above diagram as an example. The unit vector k is pointing upwards on the z axis, and so the first three components are (0,0,1). We wish to rotate by 180 degrees, and so the fourth argument is pi... and so:
>> M = vrrotvec2mat([0 0 1 pi])
M =
-1.0000 -0.0000 0
0.0000 -1.0000 0
0 0 1.0000
This exactly defines a rotation of 180 degrees around the z-axis if you take a look at the standard rotation matrix in Cartesian space around the z axis. If you recall the rotation matrix for this, it's:
If you substitute theta = pi in the above matrix, you will get the same thing as M as seen in the vrrot2vec2mat function. However, ignore the sign of the first row, second column as it's due to numerical precision... which leads us to the second parameter options. Basically, when computing the rotation matrix values using the Rodrigues Rotation formula, there will be times where values in the matrix will be quite small. The options structure has a field called epsilon, where you can specify anything smaller than this threshold is considered zero after the matrix has been calculated. The default of 1e-12 is quite suitable IMHO.
If you'd like to change the default epsilon, simply create a structure that has a single element epsilon that changes this threshold and call the function with this additional second argument... so something like:
>> options.epsilon = 1e-15;
>> M = vrrotvec2mat([0 0 1 pi], options);
In any case, going back to what we were talking about, let's say our given vector v is with respect to the above figure and that it's pointing northwest - specifically at (x,y,z) = (1,0,1). If we use this rotation matrix and rotate this point, we should get it to be parallel to the xz plane and pointing in the opposite direction, and so we should get (x,y,z) = (-1,0,1):
>> M*[1;0;1]
ans =
-1.0000
0.0000
1.0000
You can also get the same result by using the Rodrigues Rotation formula:
>> v = [1;0;1];
>> k = [0;0;1];
>> theta = pi;
>> vrot = v*cos(theta) + cross(k,v)*sin(theta) + k*(k.'*v)*(1-cos(theta))
vrot =
-1.0000
0.0000
1.0000
All in all, it's just another way of rotating a vector around an arbitrary axis, not just limited to the standard x, y or z.
I have given 3d points of a scene or a subset of these points comprising one object of the scene. I would like to create a depth image from these points, that is the pixel value in the image encodes the distance of the corresponding 3d point to the camera.
I have found the following similar question
http://www.mathworks.in/matlabcentral/newsreader/view_thread/319097
however the answers there do not help me, since I want to use MATLAB. To get the image values is not difficult (e.g. simply compute the distance of each 3d point to the camera's origin), however I do not know how to figure out the corresponding locations in the 2d image.
I could only imagine that you project all 3d points on a plane and bin their positions on the plane in discrete, well, rectangles on the plane. Then you could average the depth value for each bin.
I could however imagine that the result of such a procedure would be a very pixelated image, not being very smooth.
How would you go about this problem?
Assuming you've corrected for camera tilt (a simple matrix multiplication if you know the angle), you can probably just follow this example
X = data(:,1);
Y = data(:,1);
Z = data(:,1);
%// This bit requires you to make some choices like the start X and Z, end X and Z and resolution (X and Z) of your desired depth map
[Xi, Zi] = meshgrid(X_start:X_res:X_end, Z_start:Z_res:Z_end);
depth_map = griddata(X,Z,Y,Xi,Zi)
I am using ray tracing and at the beginning I assumed a plane surface so I used the equation of the plane surface which is :
Ax + BY + CZ +d = 0
while A,B and C are the component of the normal vector of the Plane Normal = [A B C]
and using the Ray equation : Ray = Source + t*Direction
And then solve it for t and I can find the intersection points.
My question now that I have function in matlab to read the surface of the object but the object may not be plane surface and I am getting the data of the surface [X Y Z] of the surface but I don't know which equation should I use to find t and then the intersection point. And I even have a function to give me the normal vector at each point
If you can edit the tags the get the right ones please do it.
It might not be a plane, but you can always calculate a normal vector at each point. You'll just have to work harder to do it. Take two partial derivatives in planar coordinates, cross those vectors, and that's the normal at the point.
If your surface is defined as a height Z on a some X-Y grid, you can solve it easily using fzero. This would exclude some complex shapes, but might work for standard optics problems like a ray hitting a lens. Assume that X, Y and Z are 2-d matrices with the same shape. You can then do a 2d interpolation like
z_interp = interp2(X,Y,Z,x_interp,y_interp)
If this is not the case, you should try to define your own function that can calculate z based on x and y.
For the line, we have
x_ray = x_source + t * x_dir
y_ray = y_source + t * y_dir
z_ray = z_source + t * z_dir
So you can now define a function that calculates the height above the surface as a function of t as
height_above_plane = #(t) z_source + t * z_dir - interp2(X, Y, Z, ...
x_source + t*x_dir, y_source + t*y_dir)
Note that this might not be the shortest distance from the point to the plane, it is just the height measured along the z-direction. The time the ray hits the surface can now be found by searching for the t for which the height is zero. This can be done for arbitrary functions using fzero:
t_intercept = fzero(height_above_plane, 0);
This should work well for simple cases where the function defining the surface is relatively smooth and the ray crosses the surface only once. It might be possible to transform cases with more complex geometry into such a simple case.
If you can get the X Y Z of the surface and you said you can get the normal vector in each point so what is your problem now?
The X Y Z of the surface are the intersection points and if you have the normal vector in each point so you can calculate whatever you want ( the reflected or the refracted rays).
I think you have no troubles at all
I am trying to artificially manipulate a 2D image using a rigid 3D transformation (T). Specifically, I have an image and I want to transform using T it to determine the image if captured from a different location.
Here's what I have so far:
The problem reduces to determining the plane-induced homography (Hartley and Zisserman Chapter 13) - without camera calibration matrices this is H = R-t*n'/d.
I am unsure, however, how to define n and d. I know that they help to define the world plane, but I'm not sure how to define them in relation to the first image plane (e.g. the camera plane of the original image).
Please advise! Thanks! K
Not sure what you mean by "first image plane": the camera's?
The vector n and the scalar d define the equation of the plane defining the homography:
n X + d = 0, or, in coordinates, n_x * x + n_y * y + n_z * z + d = 0, for every point X = (x, y, z) belonging to the plane.
There are various ways to estimate the homography. For example, you can map a quadrangle on the plane to a rectangle of known aspect ratio.
Or you can estimate the locations of vanishing points (this comes handy when you have, say, an image of a skyscraper, with nice rows of windows). In this case, if p and q are the homogeneous coordinates of the vanishing points of two orthogonal lines on a plane in the scene, then normal to the plane in camera coordinates is simply given by (p X q) / (|p| |q|)
I want to calculate the magnetic field from a given image using biot savarts law. For example if I have a picture of a triangle, I say that this triangle forms a closed wire carrying current. Using image derivatives I can get the co-ordinates and direction of the current (normals included). I am struggling implementing this...need a bit of help with logic too. Here is what I have:
Img = imread('littletriangle.bmp');
Img = Img(:,:,1);
Img = double(Img);
[x,y] = size(Img);
[Ix, Iy] = gradient(Img);
biot savart equation is:
b = mu/4*pi sum(Idl x rn / r^2)
where mu/4pi is const, I is current magnitude, rn distance unit vector between a pixel and current, r^2 is the squared magnitude of the displacement between a pixel and the current.
So just to start off, I read the image in, turn it into a binary and then take the image gradient. This gives me the location and orientation of the 'current'. I now need to calculate the magnetic field from this 'current' at every pixel in the image. I am only interested in getting the magnetic field in the x-y plane. anything just to start me off would be brilliant!
For wire
B = mu * I /(2*pi*r)
B is vector and has. Direction is perpendicular on line between wire an point of interest. Fastest way to rotate vector by 90° is just swapping (x.y) so it becomes (y,x) vector
What about current? If you deal whit current then current is homogenous inside of wire (can be triangle) and I in upper direction is just normalized I per point and per Whole I.
So how to do this?
Get current per pixel (current / number of pixel in shape)
For each point calculate B using (r calculated form protagora) as sum of all other mini wires expressed as pixel using upper equation. (B is vector and has also direction, so keep track of B as (x,y) )
having picture of 100*100 will yield (100*100)*(100*100) calculations of B equation or something less if you will not calculate filed from empty space.
B is at the end instead of just mu * I /(2*pi*r) sum of all wire and I becomes dI
You do not need to apply any derivatives, just integration (sum)