You are on page 1of 9

L thuyt v camera calibration

00:13 Computer Vision and Application


Camera calibration (ti khng bit nn dch ra ting Vit nh th no cho d hiu nht na) l mt phng php
tnh ton v thc nghim nhm tm ra cc thng s ca camera cho vic ti to khng gian 3D ca mt cnh no
trong thc t bng nhng nh m camera chp li c. c c nhng thng s , cc tnh ton sau
ch yu da vo m hnh camera thng dng nht hin nay: m hnh Pinhold.
V mt hnh hc, m hnh ny bao gm mt mt phng nh I (Image plane) v mt tm im C (Eyepoint) nm
trn mt phng tiu c F (Focal plane), m hnh nh sau:

Mt c im rt c bn ca m hnh ny l tt c nhng im nh m trn mt phng nh I c to thnh bi


im vt M qua C s l thng hng vi C v M, c ngha m, C, M l nm trn mt ng thng. im C cn c
gi l tm quang (Optical center), ng thn cC vung gc vi I v F c gi l trc quang (Optical axis), c
c gi l im chnh (Principal point).
Gi (C,X,Y, Z) l h ta camera, (c,x,y) l h ta ca cc im nh. Ta c th thy rng r
rang x/X = y/Y = f/Z (1).
T gc hnh hc m ni, s khng c s khc bit g khi thay mt phng I bng mt mt phng o nm pha
bn kia mt phng F. Trong h ta mi ny, mi im (x,y) gi y s c ta 3D l (x,y,f).

Trong php chiu hnh hc ta bit rng tt c nhng im nm trn mt ng thng vung gc vi mt phng
chiu th khi chiu xung mt phng ta ch thu c mt im duy nht, do vi bt k mt im (X,Y,Z)
no th t l sau s(X,Y,Z) hay (sX, sY, sZ) (vi s bt k) khi chiu qua im C ta cng ch thu c mt im
m(x,y) duy nht. T lp lun trn v (1) ta c:
1
Phng trnh (1) c th c vit li nh sau:

Trong , x = [x, y]T v t x = [x,y,1] l vector x thm 1 vo phn t cui cng. Ma trn:

gi l ma trn chiu phi cnh.


Nh vy vi mi mt im M(X,Y,Z) v mt im nh tng ng m(x,y) ta c th vit li
sm = PM (3) trong m(x,y,1) v M(X,Y,Z,1).
Trong thc t th mt i tng tht c th biu din bi mt h ta 3D bt k m khng phi l ta camera
nh ta gi s. tnh ton c trn cc h ta ny, cch n gin nht l ta chuyn n v h ta camera.
Gi s rng Mw la mt im bt k trong h ta w bt k, Mc l mt im trong h ta camera. Khi , Mw
c th chuyn v Mc bng mt php quay R v mt php tnh tin t.
Mc = RMw + t.
Hay tng qut hn, Mc = DMw (4) trong :

Ma trn R v vector t m t hng, v tr tng i gia h ta camera v h ta thc t (word cs). Ma trn
R cha 3 php quay (theo x,y,z) v vector v cha 3 php tnh tin. Nhng thng s cha trong R v t c gi l
nhng thng s ngoai ca camera (extrinsic).

2
T (3) v (4) ta c: m = PM = PDMw. (5)
Trong thc t, tm ca nh khng phi lc no cng l im chnh c. v t l theo cc trc x, y khng phi lc no
cng nh nhau. Ngi ta s dng mt ma trn K din t nhng sai lch v cui cng mi quan h gia mt
im trong thc t Mw v mt im nh m c th c din t t cng thc sau:
m = KPDMw (6)
hay c th hn :

Ma trn K c gi l ma trn thng s ni ca camera, n gm 5 thng s sau:

Trong , ku, kv l t l dc theo hai trc ca nh. u0, v0 l im chnh ca h ta nh(gc ta , thay cho c
trn). Gc theta th hin mo gia hai trc u, v. nu trong nh l tng (u,v) vung gc vi nhau th gc ny
bng 0.

C c mi quan h gia cc im nh v im ngoi thc t ng ngha vi vic ta c th ti ta li nhng


im thc t 3D da trn cc nh thu c, tuy nhin vic u tin v quan trng l ta phi tm ra c cc thng
s ca camera. C 5 thng s ni v 12 thng s ngoi (9 thnh phn ca vector quay R v 3 thnh phn ca vector
tnh tin t) cn phi tm. Vic i tm cc thng s ny c gi l qu trnh calibrate camera. V mi camera c
ng knh, khc nhau, v tr khc nhau nn khng c mt thng s chung cho tt c cc loi camera, ta phi lam
cho tng camera mt. thc hnh tm ra cho vic tm ra cc thng s ca camera cc bn c th c y, hoc
nng cao hn na th c bi vit ca mnh bng ting anh ti y.

3
Implementation of camera calibration using 3 linear
points
01:00 Computer Vision and Application

In this post, I will show you how to implement the camera calibration using method of Jie Zhao, Dong-Ming Yan, Guo-
Zun Men and Ying-Kang Zhang according to their paper: A method of calibrating the intrinsic and extrinsic
camera parameters separately for multi-camera system, issued in the Sixth International Conference Machine
Learning and Cybernetics, Hong Kong, 19-22 August 2007.
Please be sure you understand the method before reading the next. You can find the concept of method by searching
in the internet or just click here to download the paper. This post only care about the implementation!

1. Preparation

It is easy to do the following:

- Set up a C/C++ compiler (Visual Studio, Eclipse CDT, DEV C++ ...)

- Download the latest OpenCV library.

- Download a math library, I suggest you to use Engen library. You can find it here.

- Integrate all libray into your compiler.

2. Data collection

We use camera which need to be calibrated to capture the image contained 2 small balls. Each ball presents the point.

B and C lie on a line and are observable points which can be detected by using the Hough transformation.
A is an unobservable point and it's position is calculated according to the position of B and C.
We will capture N (N = 100 for example) images and find N positions of B and C. These positions then will be written
in a data file for the purpose of calibrating below.

4
Code for collecting data:

#include <...> ---> All neccessary headers!

cv::Point A(100, 100); //You can use the Paint in Window to get the pos of A

// To ditermine where is B and where is C, we compare these positions by calculating the


distances from each point to A.

double point_dist(cv::Point B)
{
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
//Read all images in a folder, calculate the position of B, C and store these in a file.

void data_collection(QString img_path)


{
// I am using QT here to read image files in the folder, you can use others
//like dirent.h ....

cv::Mat src;
ofstream data_file("data.txt");
QDirIterator files(img_path);
while(files.hasNext())
{
files.next();
if(files.fileInfo().completeSuffix() == "bmp" ||
files.fileInfo().completeSuffix() == "jpg")
{
QString file = img_path + "\\" + files.fileName();
src = cv::imread(file.toStdString(), CV_LOAD_IMAGE_GRAYSCALE)
std::vector<Vec3f> circles;
cv::HoughCircles(src, circles, CV_HOUGH_GRADIENT, 1,
src_gray.rows/8, 200, 100, 0, 0 );
//We just desire to detect 2 circles.
if(circles.size() != 2) continue;
cv::Point B(cvRound(circles[0][0], cvRound(circles[0][1]);
cv::Point C(cvRound(circles[1][0], cvRound(circles[1][1]);
//Store these points in a file
point_dist(B, A) > point_dist(C, A) ?
data_file << B : data_file << C;
data_file << "\n";

}
}

data_file.close();
}

5
3. Calculate camera intrinsics.

std::vector<double> camera_intrinsic()
{
using namespace Eigen;
std::vector<double> results;
double u0, v0, anpha, beta, gamma;
double Za;
double L = 2.0;
double la = 0.6;
double lb = 0.4;
double temp1, temp2;
int i = 0, j = 0;
MatrixXd V(N,6);
MatrixXd Q(N,2);
VectorXd l(N);
VectorXd s(2);
double xb, yb, xc, yc;
Vector3d a(3), b(3), c(3), h(3);
VectorXd x;
VectorXd e = VectorXd::Ones(N);
double b11, b12, c11, c12;
std::ifstream file("data.txt");
while(file >> xb >> yb >> xc >> yc) {
Q.row(j) << yc - yb, xb - xc;
l(j) = xb*(yc - yb) + yb*(xb - xc);
j++;
}
file.close();
file.open("data.txt");
s = (Q.transpose()*Q).inverse()*Q.transpose()*l;
a<<s[0], s[1], 1;
if(file.is_open()){
while(file >> b11 >> b12 >> c11 >> c12) {
b<<b11, b12, 1; c<<c11, c12, 1;
temp1 = (a.cross(c)).dot(b.cross(c));
temp2 = (b.cross(c)).dot(b.cross(c));
h = a + ((la*temp1)/(lb*temp2))*b;
V.row(i) << h(0)*h(0), 2*h(0)*h(1), h(1)*h(1),
2*h(0)*h(2), 2*h(1)*h(2), h(2)*h(2);
i++;
}
}
x = (L*L)*((((V.transpose()*V).inverse())*V.transpose())*e);
v0 = (x(1)*x(3) - x(0)*x(4))/(x(0)*x(2) - x(1)*x(1));
Za = sqrt(x(5) - (x(3)*x(3) + v0*(x(1)*x(3) - x(0)*x(4)))/x(0));
anpha = Za/sqrt(x(0));
beta = Za*sqrt(fabs(x(0)/(x(0)*x(2) - x(1)*x(1))));
6
gamma = -(x(1)*anpha*anpha*beta)/(Za*Za);
u0 = v0*gamma/beta - x(3)*anpha*anpha/(Za*Za);
results.push_back(u0);
results.push_back(v0);
results.push_back(anpha);
results.push_back(beta);
results.push_back(gamma);
return results;

4. Calculate camera extrinsics

Chose 4 points according to your own real cordinate system to calculate the extrinsics of camera. It is simple, --->> no
code for this section :)

Calibrate camera s dng bn c (Camera calibration


using chessboard)
23:37 Computer Vision and Application

Trong bi ny ti s gii thiu cch ci t camera calibration s dng th vin OpenCV C++ thu c bng cc
thng s ni ca camera (camera intrinsic). Cc bn xem thm ti y c qua khi nim c bn v camera
calibration.
Cng vic cn chun b trc.
Chun b mt bn c (loi bn c vua). Kch thc ca bn c l ty , tuy nhin khng nn qu nh so vi tm nhn
ca camera, thng thng nn in bn c trn mt kh giy A0 l va. S lng cc trn bn c c th l 8x8,
7x10 ... Min l din tch cc vung phi bng nhau. Nu in bn c trn giy, nn chng trn mt mt phng
(tm knh, g ...) chng lun c phng, khng b bin dng.

Sau khi c bn c, ta dng camera t mt v tr c nh, duy chuyn bn c quanh camera vi nhng gc nhn
khc nhau, tng v tr ta chp li nh cha bn c. S lng nh c th l vi chc ci.( Thng thng ti hay
chp 50 kiu nh 50 gc nhn khc nhau). Ta lu s nh ny vo mt folder lm c s d liu cho cc tnh ton
sau ny.

Lp trnh camera calibration


Chng trnh s dng th vin OpenCV C++, ti s dng trnh dch Eclipse c s gip ca QT. Ton b code rt
n gin v c ch thch r rng, ch ring mc c cc file nh trong mt folder ti s dng lp QDirIterator ca QT.
Nu cc bn khng dng QT c th dng bt k th vin no min l c c cc file trong folder (Nh cc th
vin ca MFC hoc th vin ring v file v folder dirent.h ...).
Trc ht hy to mt project mi hot ng vi OpenCV. Sau hy pass on code sau :

7
#include ... //include tt c cc header cn thit.

void cva_calib(QString img_path)


{
int numCornersHor = 14;
int numCornersVer = 10;
int numSquares = numCornersHor*numCornersVer;
int error = 0;
cv::Size board_sz = cv::Size(numCornersHor, numCornersVer);
std::vector<std::vector<cv::Point3f>> object_points;
std::vector<std::vector<cv::Point2f>> image_points;
std::vector<cv::Point2f> corners;
std::vector<cv::Point3f> obj;
for(int j=0;j<numSquares;j++)
obj.push_back(cv::Point3f((j/numCornersHor)*0.3, (j%numCornersHor)*0.3, 0.0f));

cv::Mat src;
cv::Mat gray;
QDirIterator files(img_path);
while(files.hasNext())
{
files.next();
if(files.fileInfo().completeSuffix() == "bmp")
{
QString file = img_path + "\\" + files.fileName();
std::cout<<"Image file "<<file.toStdString()<<std::endl;

src = cv::imread(file.toStdString());
cv::cvtColor(src, gray, CV_RGB2GRAY);
bool found = cv::findChessboardCorners(gray, board_sz, corners, CV_CALIB_CB_ADAPTIVE_THRESH);
if(found)
{
std::cout<<"Find chessboard corner --> OK"<<std::endl;
cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1),
cv::TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 30, 0.1));
cv::drawChessboardCorners(src, board_sz, corners, found);
image_points.push_back(corners);
object_points.push_back(obj);

}
else
{
std::cout<<"Find chessboard corner --> FALSE"<<std::endl;
error++;
}
}

}
cv::namedWindow("a",0);
cv::imshow("a", src);

cv::Mat intrinsic = cv::Mat(3, 3, CV_32FC1);


cv::Mat distCoeffs(1, 5, CV_32FC1);
distCoeffs.at<float>(0, 4) = 0;
std::vector<cv::Mat> rvecs;
std::vector<cv::Mat> tvecs;
cv::calibrateCamera(object_points, image_points, gray.size(), intrinsic, distCoeffs, rvecs, tvecs,
CV_CALIB_FIX_K3);

std::cout<<"------------------------------------------"<<std::endl;
std::cout<<"Total image false: "<<error<<std::endl;
std::cout<<"Intrinsic "<<"\n"<<intrinsic<<std::endl;
std::cout<<"Distort coeffs"<<"\n"<<distCoeffs<<std::endl;

}
int main(int argc, char* argv[])
{
if(argc < 1) return;
else

8
{
QString img_path = argv[1];
cva_calib(img_path);
}
return 0;
}

kt qu cui cng c lu trong ma trn 3x3 intrinsic. Cc bn c th s dng kt qu ny cho mc ch sau ny


ca mnh!

You might also like