Professional Documents
Culture Documents
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:
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 :
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.
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
- Set up a C/C++ compiler (Visual Studio, Eclipse CDT, DEV C++ ...)
- Download a math library, I suggest you to use Engen library. You can find it here.
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:
cv::Point A(100, 100); //You can use the Paint in Window to get the pos of 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.
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;
Chose 4 points according to your own real cordinate system to calculate the extrinsics of camera. It is simple, --->> no
code for this section :)
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.
7
#include ... //include tt c cc header cn thit.
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);
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;
}