How to stick object inside fov - three.js

I'm trying to figure out how to position an object inside the edge of the camera's fov if it goes outside of it.
I've looked at this: Three.js - Width of view
But if I plug in the values, it returns 5.12 if the screen width is 512, and 3.12 for height if the screen height is 320.
I have the camera positioned -150 on the z axis, and the objects are located at 0 on the z axis.
I was hoping it would tell me how much x and y distance there is visible in the fov where z axis is 0 if camera is looking along the z axis. That way I could position objects if they go outside the limits.
Anyone know how to get this data?

Okay, I found the answer. Had to use some trigonometry.
h = tan(fov/2)*dist
dist is the distance to the object from the camera. h is half of the screen space in y axis.
to get x axis multiply by (screenwidth/screenheight)

Related

Inverse Camera Intrinsic Matrix for Image Plane at Z = -1

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

three.js: Y-rotation of group, relative to camera

Even after hours of googling, I can't really get my head around this. Maybe somebody here can help me a bit with this.
I basically want to determine the Y-rotation of an object (that is always in the viewport's center), relative to my camera. Imagine the object standing on the center of a record player/turntable, that slowly rotates around its Y axis, and my camera always facing the center of that object while using OrbitControls to change the cam's position around the object. Imagine the camera not moving, but the turntable turning, one revolution equals this Y rotation to be between 0° and 360°.
For example, this Y rotation would be:
0° when cam's position is [x=0, y=0, z=100], or [x=0, y=100, z=200] (the cam's y position doesn't matter, it always looks down/up to the group's center),
45° when cam's position is [x=100, y=0, z=100] or [x=100, y=200, z=100],
90° when cam's position is [x=100, y=0, z=0] or [x=200, y=100, z=0], etc.
Thing is, both of these can have some pretty random positions & rotations in the world coordinate system, so it's not given that the object's position is [x=0, y=0, z=0].
Any ideas? Thanks a lot!
I'm not sure if I'm being helpful, but perhaps Object3D.getWorldQuaternion and Quaternion.angleTo() might help?
something like :
const cameraQuaternion = new THREE.Quaternion();
camera.getWorldQuaternion(cameraQuaternion);
const targetQuaternion = new THREE.Quaternion();
target.getWorldQuaternion(targetQuaternion);
const delta = cameraQuaternion.angleTo(targetQuaternion);
const euler = new THREE.Euler().setFromQuaternion(delta);
console.log(euler.y / Math.PI * 180);

Turn a 2D Image into a rotating 3D image on Matlab

I would like to know how to rotate a 2D image along its Z-axis using Matlab R2016b and to obtain an image after performing this procedure.
For example, let's take this 2D image:
Now, I rotate it of 45° roughly:
And now, of 90°:
Do you know if it is possible to perform the same operation in Matlab R2016b, please ?
Thank you very much for your help
Images Source: https://www.youtube.com/watch?v=m89mVexWQZ4
Yes it's possible. The easiest thing to do would be to map the image on the y = 0 plane in 3D, then rotate the camera to the desired azimuth or the angle with respect to the y axis. Once you do that, you can use the getframe / cdata idiom to actually capture the actual image data in a variable itself. The reason why you do this with respect to the y plane is because the method that I will be using to present the image is through the surf command that plots surface plots in 3D, but the y axis here is the axis that goes into and out of the screen. The x axis is the horizontal and the z axis would be the vertical when displaying data.
First read in your image using something like imread, then you need to define the 4 corners of the image that map to the 3D plane and then rotate the camera. You can use the view function to help you rotate the camera by adjusting the azimuthal angle (first parameter) and leaving the elevation angle as 0.
Something like this could work. I'll be using the peppers image that is part of the image processing toolbox:
im = imread('peppers.png'); % Read in the image
ang = 45; % Rotate clockwise by 45 degrees
% Define 4 corners of the image
X = [-0.5 0.5; -0.5 0.5];
Y = [0 0; 0 0];
Z = [0.5 0.5; -0.5 -0.5];
% Place the image on the y = 0 plane
% Turn off the axis and rotate the camera
figure;
surf(X, Y, Z, 'CData', im, 'FaceColor', 'texturemap');
axis('off');
view(ang, 0);
% Get the image data after rotation
h = getframe;
rot_im = h.cdata;
rot_im contains the rotated image. To appreciate the rotation of the image, we can loop through angles from 0 to 360 in real time. At each angle, we can use view to dynamically rotate the camera and use drawnow to update the figure. I've also updated the title of the figure to show you what the angle is at each update. The code for that is below as well as the output saved as an animated GIF:
for ang = 0 : 360
view(ang, 0);
pause(0.01);
drawnow;
title(sprintf('Angle: %d degrees', ang));
end

Place small object inside of big object by angle

What we have is angle(0-360), our small object is in the center and we have width and height of each object. I have tried to do dividing widths and heights without success. Task is to place small object in the bottom of the big object, and when big object get rotated we need small object be on the bottom again, but that bottom could be up or left or right, that why i guessed we need the angle.
So basically we need to create circle movement of small object. Radius of that circle will be big object height/2. But how to calculate X and Y locations from the center to place the small object?
Represantation in images:
Here we have the default state with angle 0
Here we have angle 47
And here we have angle 227
Lets say you want to calculate your new coordinates r pixels away from the point (X,Y) for an angle a. And if your new coordinates would be (x1, y1),
x1 = X + r * COS(a)
y1 = Y + r * SIN(a)
Here is some more info and techniques

How to position the camera so that my main object is entirely visible and fit to the screen?

The object is in the center of the 3D plane. I know the object's bounds.
For the 3D plane, X is from left to right, Y is from bottom to top, and Z is from inside of the screen to the outside. The object is facing positive Z direction.
I want to place my camera in X=0, Y=0, and Z=somewhere so that the camera can see the whole object from its left-most to right-most, top-most to bottom-most, and its front side.
So guys, please help me here, Z= ...?
Formula
Let R be the radius of the bounding sphere for your object.
Let V be the vertical field of view angle, 0 < V < 90 degrees.
Let H be the horizontal field of view angle, 0 < H < 90 degrees.
Then the distance you need to place your camera from the object is Z = R / sin(min(V,H)).
Derivation
Here is what the derivation is for the distance Z needed for a full vertical view of the object. Solve for Z to get Z = R / sin(V).
A similar derivation for the distance Z needed for a full horizontal view gives Z = R / sin(H). Since we want both a full vertical and horizontal view, we use Z = max(R / sin(V), R / sin(H)) = R / sin(min(V,H)).

Resources