9

Calibration:

I have calibrated the camera using this vision toolbox in Matlab. I used checkerboard images to do so. After calibration I get the cameraParams which contains:

Camera Extrinsics
RotationMatrices: [3x3x18 double]
TranslationVectors: [18x3 double]

and

 Camera Intrinsics
 IntrinsicMatrix: [3x3 double]
 FocalLength: [1.0446e+03 1.0428e+03]
 PrincipalPoint: [604.1474 359.7477]
 Skew: 3.5436

Aim: I have recorded trajectories of some objects in motion using this camera. Each object corresponds to a single point in a frame. Now, I want to project the points such that I get a top-view.

  1. Note all these points I wish to transform are are the on the same plane.

    ex: [xcor_i,ycor_i ]

    -101.7000  -77.4040
    -102.4200  -77.4040
    
  2. KEYPOINT: This plane is perpendicular to one of images of checkerboard used for calibration. For that image(below), I know the height of origin of the checkerboard of from ground(193.040 cm). And the plane to project the points on is parallel to the ground and perpendicular to this image.

Figure 1

Code (Ref:https://stackoverflow.com/a/27260492/3646408 and answer by @Dima below):

function generate_homographic_matrix()
%% Calibrate camera
% Define images to process
path=['.' filesep 'Images' filesep];
list_imgs=dir([path '*.jpg']);
list_imgs_path=strcat(path,{list_imgs.name});

% Detect checkerboards in images
[imagePoints, boardSize, imagesUsed] = detectCheckerboardPoints(list_imgs_path);
imageFileNames = list_imgs_path(imagesUsed);

% Generate world coordinates of the corners of the squares
squareSize = 27;  % in units of 'mm'
worldPoints = generateCheckerboardPoints(boardSize, squareSize);

% Calibrate the camera
[cameraParams, imagesUsed, estimationErrors] = estimateCameraParameters(imagePoints, worldPoints, ...
    'EstimateSkew', true, 'EstimateTangentialDistortion', true, ...
    'NumRadialDistortionCoefficients', 3, 'WorldUnits', 'mm');
%% Compute homography for peripendicular plane to checkerboard
% Detect the checkerboard 
im=imread(['.' filesep 'Images' filesep 'exp_19.jpg']); %exp_19.jpg is the checkerboard orthogonal to the floor
[imagePoints, boardSize] = detectCheckerboardPoints(im);

% Compute rotation and translation of the camera.
[Rc, Tc] = extrinsics(imagePoints, worldPoints, cameraParams);

% Rc(rotation of the calibration view w.r.t the camera) = [x y z])
%then the floor has rotation Rf = [z x -y].(Normal vector of the floor goes up.)
Rf=[Rc(:,3),Rc(:,1),Rc(:,2)*-1];

% Translate it to the floor
H=452;%distance btw origin and floor
Fc = Rc * [0; H; 0];
Tc = Tc + Fc';

% Combine rotation and translation into one matrix:
Rf(3, :) = Tc;

% Compute the homography between the checkerboard and the image plane:
H = Rf * cameraParams.IntrinsicMatrix;

save('homographic_matrix.mat','H')
end

%% Transform points
function [x_transf,y_transf] =transform_points(xcor_i,ycor_i)
% creates a projective2D object and then transforms the points forward to
% get a top-view
% xcor_i and ycor_i are 1d vectors comprising of the x-coordinates and
% y-coordinates of trajectories. 
data=load('homographic_matrix.mat');
homo_matrix=data.H;
tform=projective2d(inv(homo_matrix));
[x_transf,y_transf] = transformPointsForward(tform,xcor_i,ycor_i);
end

Quoting text from OReilly Learning OpenCV Pg 412: "Once we have the homography matrix and the height parameter set as we wish, we could then remove the chessboard and drive the cart around, making a bird’s-eye view video of the path..." This what I essentially wish to achieve.

Community
  • 1
  • 1
Abhishek Bhatia
  • 9,404
  • 26
  • 87
  • 142
  • 3
    If you don't have any depth information about the points, or other 3D information about the object or scene, camera calibration is not enough to convert 2D points in the image to exact 3D. You can only place them on a 3D ray. – Photon Dec 25 '15 at 12:05
  • @Photon I don't want to convert them to 3D. I still want the 2D points only from top perspective. – Abhishek Bhatia Dec 25 '15 at 12:07
  • 3
    The two are equivalent mathematically. – Photon Dec 25 '15 at 12:08
  • @photon http://stackoverflow.com/questions/15768651/generating-a-birds-eye-top-view-with-opencv My problem is easier since I just have to generate bird's eye view of the pixel coordinates, not the image – Abhishek Bhatia Dec 25 '15 at 12:11
  • 2
    In that link, the extra information is the size of the squares on the grid object. As I said before, if you have information about sizes, then you can resolve it, but not for general case points in the image. – Photon Dec 25 '15 at 12:15
  • I do have information about the size of the squares. The calibration I adopted is exactly as mentioned in http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html. – Abhishek Bhatia Dec 25 '15 at 12:17
  • @Photon Can you illustrate what other 3D information of scene you are referring to here. – Abhishek Bhatia Jan 28 '16 at 02:20
  • One example is knowledge about object sizes which constrains the 3D distance between points. Another example is if you know that the points are situated on a certain plane, like the floor, which constrains one coordinate. – Photon Jan 28 '16 at 04:42

2 Answers2

1

Abhishek,

I don't entirely understand what you are trying to do. Are your points on a plane, and are you trying to create a bird's eye view of that plane?

If so, then you need to know the extrinsics, R and t, describing the relationship between that plane and the camera. One way to get R and t is to place a checkerboard on the plane, and then use the extrinsics function.

After that, you can follow the directions in the question you cited to get the homography. Once you have the homography, you can create a projective2D object, and use its transformPointsForward method to transform your points.

Community
  • 1
  • 1
Dima
  • 38,860
  • 14
  • 75
  • 115
  • Thanks for the answer. I have now added more information in the question. Please check `New info` in the question. – Abhishek Bhatia Jan 29 '16 at 13:24
  • 1
    Ok, so that means you know the transformation from the camera's coordinates to the checkerboard coordinates: R1, t1. You should also be able to figure out the transformation between the checkerboard and your perpendicular plane: R2, t2. You would need to pick some point on that plane as the origin. Now you can combine the two transformations to get R3, t3, the transformation from the camera to the plane of interest. – Dima Jan 29 '16 at 13:35
  • Can you provide info on each step. Some code/psuedocode is greatly appreciated. Sry I am new to vision. Please update your answer. – Abhishek Bhatia Jan 29 '16 at 13:52
  • Thanks for the comment. Can you please tell how to figure out R2, t2. – Abhishek Bhatia Feb 03 '16 at 07:24
  • Some more details on transformations using variables in the question would be great. Please do so if possible. – Abhishek Bhatia Feb 06 '16 at 16:05
  • Please check edit 2 if possible. Thanks. Please elaborate more on "You should also be able to figure out the transformation between the checkerboard and your perpendicular plane: R2, t2. You would need to pick some point on that plane as the origin. Now you can combine the two transformations to get ". – Abhishek Bhatia Feb 08 '16 at 21:52
  • Can you please reply. – Abhishek Bhatia Feb 10 '16 at 21:01
  • 1
    Sorry, working out the exact math takes time, which I do not currently have. Your current coordinate system has the checkerboard as its X-Y plane. Your new coordinate system's X-Y plane is perpendicular to your current one. You need to rotate by 90 degrees about the Y axis, and then translate along the Z. Check "Rotation Matrix" on Wikipedia. – Dima Feb 10 '16 at 21:05
  • Please check the `Code` in Edit 1 once to confirm if there is any problem or not. Thanks! – Abhishek Bhatia Feb 11 '16 at 00:41
0

Since you have the size of squares on the grid, then given 2 points that you know are connected by an edge of size E (in real world units), you can calculate their 3D position.

Taking the camera intrinsic matrix K and the 3D position C and the camera orientation matrix R, you can calculate a ray to each of the points p by doing:

D = R^T * K^-1 * p

Each 3D point is defined as:

P = C + t*D

and you have the constraint that ||P1-P2|| = E then it's a matter of solving for t1,t2 and finding the 3D position of the two points.

In order to create a top view, you can take the 3D points and project them using a camera model for that top view to generate a new image.

If all your points are on a single plane, it's enough to calculate the position of 3 points, and you can extrapolate the rest.

If your points are located on a plane that you know one coordinate of, you can do it simply for each point. For example, if you know that your camera is located at height h=C.z, and you want to find the 3D location of points in the frame, given that they are on the floor (z=0), then all you have to do is calculate the direction D as above, and then:

t=abs( (h-0)/D.z )

The 0 represent the height of the plane. Substitute for any other value for other planes.

Now that you have the value of t, you can calculate the 3D position of each point: P=C+t*D.

Then, to create a top view, create a new camera position and rotation to match your required projection, and you can project each point onto this camera's image plane. If you want a full image, you can interpolate positions and fill in the blanks where no feature point was present.

For more details, you can always read: http://www.robots.ox.ac.uk/~vgg/hzbook/index.html

Photon
  • 3,182
  • 1
  • 15
  • 16
  • Can you let me know how I get the above parameters in the tool mentioned. After calibration I get this: `focal Length: fc = [ 1017.46736 1014.02509 ] +/- [ 21.95105 22.41464 ] Principal point: cc = [ 639.50000 359.50000 ] +/- [ 0.00000 0.00000 ] Skew: alpha_c = [ 0.00000 ] +/- [ 0.00000 ] => angle of pixel axes = 90.00000 +/- 0.00000 degrees Distortion: kc = [ 0.07903 -0.04146 -0.00481 -0.01371 0.00000 ] +/- [ 0.02762 0.03850 0.00213 0.00562 0.00000 ] Pixel error: err = [ 0.06366 0.07012 ]` – Abhishek Bhatia Dec 26 '15 at 14:48
  • The values you have there only specify the camera intrinsic calibration (K) which is [fc(1) 0 cc(1); 0 fc(2) cc(2); 0 0 1]. You need to get / calculate the position and orientation of the camera as well – Photon Dec 26 '15 at 14:57
  • Thanks for the continued help! Are you referring to the position of camera in the real-world and angle it is making with different axis. With respect, should I measure these? – Abhishek Bhatia Dec 26 '15 at 15:01
  • You need these, if you want to calculate the 3D position of the points in the world, which is necessary for calculating a top view. – Photon Dec 26 '15 at 15:17
  • I have the camera position `C` (x,y,z). Can you tell how to define the orientation of the camera? – Abhishek Bhatia Dec 26 '15 at 17:08
  • Try this link: https://en.wikipedia.org/wiki/Camera_resectioning#Extrinsic_parameters There are more resources online, if you search. – Photon Dec 26 '15 at 19:17
  • I have changed the question a bit, making it more clear. Please have a look. – Abhishek Bhatia Jan 22 '16 at 18:48
  • Thanks for the answer. I have now added more information in the question. Please check New info in the question. – Abhishek Bhatia Jan 29 '16 at 13:24
  • please check the updated question when possible. If possible please update your answer. – Abhishek Bhatia Feb 03 '16 at 22:52
  • Added an example of handling a horizontal plane – Photon Feb 04 '16 at 13:34
  • Please check `Edit 1`. – Abhishek Bhatia Feb 10 '16 at 23:54
  • Can you please reply. – Abhishek Bhatia Feb 11 '16 at 00:50
  • I added description of handling the horizontal plane. I'm not going to write the code here. – Photon Feb 11 '16 at 06:26