2010. 5. 18. 00:26
Computer Vision
ref.
2010/02/10 - [Visual Information Processing Lab] - R. Y. Tsai "A Versatile Camera Calibration Technique for High Accuracy 3-D Maching Vision Metrology Using Off-the-shelf TV Cameras and Lenses"
(1) 고정되어 있는 것으로 가정한 카메라의 내부 파라미터 값들을 구하고 (2) 실시간으로 들어오는 이미지 프레임마다 카메라의 회전과 이동을 계산하기 위하여 Tsai 알고리즘을 쓰기로 하고, C 또는 C++로 구현된 소스코드 또는 라이브러리를 찾아서 붙여 보기로 한다.
Try #1.
처음에는 CMU의 Reg Willson가 C로 짠 Tsai Camera Calibration 코드 에서 필요한 부분을 include하여 쓰려고 했는데, C++ 문법에 맞지 않는 구식 C 문법으로 코딩된 부분이 많아서 고치는 데 애를 먹었다. (Xcode의 C++ 프로젝트에서 .c 파일을 include하면 compile은 되지만, linking error가 난다. 때문에 .c를 .cpp로 바꾸어야 함.) 그런데 결정적으로, "cal_main.cpp" 파일에 정의된, 캘리브레이션의 최종 결과값을 주는 함수들이 호출하는 optimization을 실행하는 함수 lmdif_()가 Fortan 파일 "lmdif.f"에 정의되어 있고, Fortran을 C로 변환해 주는 "f2c.h"에 의해 이것을 "lmdif.c"로 하여 가지고 있다는 문제가 있었다. lmdif.c를 lmdif.cpp 형태로 만들기 위해서는 Fortran 언어와 Fortran을 C++로 변환하는 방법을 알아야 하므로, 결국 포기했다.
Try #2.
Michigan State University Charles B. Owen의 Display-Relative Calibration (DRC)을 구현한 DRC 프로그램( DRC.zip )에서 카메라 캘리브레이션에 Tsai의 알고리즘 libtsai.zip을 쓰고 있다. 이 라이브러리는 위의 C 코드를 C++로 수정하면서 "CTsai"라는 클래스를 사용하고 여러 함수들을 수정/보완/결합한 것인데, Visual Studio 용 프로젝트 프로그램을 만들면서 Windows 환경에 기반하여 MFC를 활용하였다. 그래서 이것을 나의 Mac OS X 기반 Xcode 프로젝트에서 그대로 가져다 쓸 수는 없다. 용법은 다음과 같다.
DRC/DisplayRelativeCalibration.cpp:
문제점#1.
class CTsai 안의 member functions 중에 ncc_compute_exact_f_and_Tz( )와 ncc_compute_exact_f_and_Tz_error( )가 있는데,
libtsai.h:21
전자인 ncc_compute_exact_f_and_Tz()가 정의된 부분을 보면,
Tsai_ncc.cpp:274
클래스 형태의 템플릿( CLmdif )으로 선언된 "lmdif"의 member function "Lmdif"를 호출할 때,
min/Lmdif.h:48
후자인 같은 member function, ncc_compute_exact_f_and_Tz_error()를 인자로 넣고 있고 (위 부분 코드들 중 오렌지 색 부분), 컴파일 하면 이 부분을 <unknown type>으로 인식하지 못 하겠다는 에러 메시지를 보낸다. 그리고 다음과 같은 형태를 추천한다고 한다.
function pointer의 형태가 틀린 모양인데, 오렌지색 부분을 그냥 함수가 아닌 어떤 class의 non-static member function을 가리키는 pointer로 &CTsai::ncc_compute_exact_f_and_Tz_error 이렇게 바꾸어 주면, 에러 메시지가 다음과 같이 바뀐다.
연두색 부분 대신 CTsai::ncc_compute_exact_f_and_Tz_error 이렇게 바꾸어 주면, 에러 메시지가 다음과 같다.
해결:
편법으로, class CLmdif를 클래스 형 템플릿이 아닌 그냥 클래스로 바꾸어서 선언하고 연두색 부분처럼 호출하면 에러는 안 나기에 일단 이렇게 넘어가기로 한다.
문제점#2.
코드에서 Windows OS 기반 MFC를 사용하고 있어 Mac OS X에서 에러가 난다.
해결:
MFC를 사용하는 "StdAfx.h"는 모두 주석 처리한다.
문제점#3.
Lmdif.h
... 기타 등등의 문제점들을 해결하고, 캘리브레이션을 수행한 결과가 맞는지 확인하자.
source code:
아래 사진은 구해진 카메라 내부/외부 파라미터들을 가지고 (1) 실제 패턴의 점에 대응하는 이미지 프레임 (image coordinate) 상의 점을 찾아 (reprojection) 보라색 원으로 그리고, (2) 실제 패턴이 있는 좌표 (world coordinate)를 기준으로 한 graphic coordinate에 직육면체 cube를 노란색 선으로 그린 결과이다.
위 왼쪽 사진에서 보여지는 16쌍의 대응점들의 좌표값을 "이미지 좌표(x,y) : 패턴 좌표 (x,y,z)"로 출력한 결과:
그런데 위 오른쪽 사진에서 보여지는 결과는 이전 프레임에서 20쌍의 대응점으로부터 구한 카메라 파라미터 값을 가지고 계산한 결과이다.
대응점 연결에 오차가 없으면, 즉, 패턴 인식이 잘 되면, Tsai 알고리즘에 의한 카메라 파라미터 구하기가 제대로 되고 있음을 확인할 수 있다. 하지만, 현재 full optimization (모든 파라미터들에 대해 최적화 과정을 수행하는 것)으로 동작하게 되어 있고, 프레임마다 모든 파라미터들을 새로 구하고 있기 때문에, 속도가 매우 느리다. 시험 삼아 reprojection과 간단한 graphic을 그리는 과정은 속도에 큰 영향이 없지만, 그전에 카메라 캘리브레이션을 하는 데 필요한 계산 시간이 길다. 입력 프레임이 들어오는 시간보다 훨씬 많은 시간이 걸려 실시간 구현이 되지 못 하고 있다.
따라서, (1) 내부 파라미터는 첫 프레임에서 한 번만 계산하고 (2) 이후 매 프레임마다 외부 파라미터 (카메라의 회전과 이동)만을 따로 계산하는 것으로 코드를 수정해야 한다.
Try#3.
OpenCV 함수 이용
1) 내부 파라미터 계산
cvCalibrateCamera2
2) lens distortion(kappa1, kappa2)을 가지고 rectification
cvInitUndistortRectifyMap
3) line detection
4) 패턴 인식 (대응점 찾기)
5) 외부 파라미터 계산 (4의 결과 & lens distortion = 0 입력)
cvFindExtrinsicCameraParams2
6) reprojection
2)에서 얻은 rectificated image에 할 것
2010/02/10 - [Visual Information Processing Lab] - R. Y. Tsai "A Versatile Camera Calibration Technique for High Accuracy 3-D Maching Vision Metrology Using Off-the-shelf TV Cameras and Lenses"
(1) 고정되어 있는 것으로 가정한 카메라의 내부 파라미터 값들을 구하고 (2) 실시간으로 들어오는 이미지 프레임마다 카메라의 회전과 이동을 계산하기 위하여 Tsai 알고리즘을 쓰기로 하고, C 또는 C++로 구현된 소스코드 또는 라이브러리를 찾아서 붙여 보기로 한다.
Try #1.
처음에는 CMU의 Reg Willson가 C로 짠 Tsai Camera Calibration 코드 에서 필요한 부분을 include하여 쓰려고 했는데, C++ 문법에 맞지 않는 구식 C 문법으로 코딩된 부분이 많아서 고치는 데 애를 먹었다. (Xcode의 C++ 프로젝트에서 .c 파일을 include하면 compile은 되지만, linking error가 난다. 때문에 .c를 .cpp로 바꾸어야 함.) 그런데 결정적으로, "cal_main.cpp" 파일에 정의된, 캘리브레이션의 최종 결과값을 주는 함수들이 호출하는 optimization을 실행하는 함수 lmdif_()가 Fortan 파일 "lmdif.f"에 정의되어 있고, Fortran을 C로 변환해 주는 "f2c.h"에 의해 이것을 "lmdif.c"로 하여 가지고 있다는 문제가 있었다. lmdif.c를 lmdif.cpp 형태로 만들기 위해서는 Fortran 언어와 Fortran을 C++로 변환하는 방법을 알아야 하므로, 결국 포기했다.
Try #2.
Michigan State University Charles B. Owen의 Display-Relative Calibration (DRC)을 구현한 DRC 프로그램( DRC.zip )에서 카메라 캘리브레이션에 Tsai의 알고리즘 libtsai.zip을 쓰고 있다. 이 라이브러리는 위의 C 코드를 C++로 수정하면서 "CTsai"라는 클래스를 사용하고 여러 함수들을 수정/보완/결합한 것인데, Visual Studio 용 프로젝트 프로그램을 만들면서 Windows 환경에 기반하여 MFC를 활용하였다. 그래서 이것을 나의 Mac OS X 기반 Xcode 프로젝트에서 그대로 가져다 쓸 수는 없다. 용법은 다음과 같다.
DRC/DisplayRelativeCalibration.cpp:
bool CDisplayRelativeCalibration::ComputeCameraCalibration(void)
{
CTsai tsai;
tsai.Width(m_camerawid);
tsai.Height(m_camerahit);
for(std::list<Corr>::const_iterator i=m_cameracorr.begin(); i!=m_cameracorr.end(); i++)
{
tsai.Point(i->x, i->y, i->z, i->u, i->v);
}
if(tsai.PointCount() < 8)
return Error("Didn't get enough points");
if(!tsai.Compute())
return Error("Camera calibration failed");
for(int n=0; n<tsai.PointCount(); n++)
{
double ux, uy;
tsai.WorldToImage (tsai.PointX(n), tsai.PointY(n), tsai.PointZ(n), ux, uy);
m_cameraproj.push_back(CGrPoint(ux, uy, 0));
}
m_cameraf = tsai.F();
m_cameracx = tsai.Cx();
m_cameracy = tsai.Cy();
m_camerakappa1 = tsai.Kappa1();
m_camerasx = tsai.Sx();
memcpy(m_cameramatrix, tsai.CameraMatrix(), sizeof(double) * 16);
return true;
}
{
CTsai tsai;
tsai.Width(m_camerawid);
tsai.Height(m_camerahit);
for(std::list<Corr>::const_iterator i=m_cameracorr.begin(); i!=m_cameracorr.end(); i++)
{
tsai.Point(i->x, i->y, i->z, i->u, i->v);
}
if(tsai.PointCount() < 8)
return Error("Didn't get enough points");
if(!tsai.Compute())
return Error("Camera calibration failed");
for(int n=0; n<tsai.PointCount(); n++)
{
double ux, uy;
tsai.WorldToImage (tsai.PointX(n), tsai.PointY(n), tsai.PointZ(n), ux, uy);
m_cameraproj.push_back(CGrPoint(ux, uy, 0));
}
m_cameraf = tsai.F();
m_cameracx = tsai.Cx();
m_cameracy = tsai.Cy();
m_camerakappa1 = tsai.Kappa1();
m_camerasx = tsai.Sx();
memcpy(m_cameramatrix, tsai.CameraMatrix(), sizeof(double) * 16);
return true;
}
문제점#1.
class CTsai 안의 member functions 중에 ncc_compute_exact_f_and_Tz( )와 ncc_compute_exact_f_and_Tz_error( )가 있는데,
libtsai.h:21
class CTsai
{
bool ncc_compute_exact_f_and_Tz();
bool ncc_compute_exact_f_and_Tz_error (int m_ptr, int n_ptr, const double *params, double *err);
};
{
bool ncc_compute_exact_f_and_Tz();
bool ncc_compute_exact_f_and_Tz_error (int m_ptr, int n_ptr, const double *params, double *err);
};
전자인 ncc_compute_exact_f_and_Tz()가 정의된 부분을 보면,
Tsai_ncc.cpp:274
bool CTsai::ncc_compute_exact_f_and_Tz()
{
CLmdif<CTsai> lmdif;
lmdif.Lmdif (this, ncc_compute_exact_f_and_Tz_error,
m_point_count, NPARAMS, x,
NULL, NULL, NULL, NULL);
}
{
CLmdif<CTsai> lmdif;
lmdif.Lmdif (this, ncc_compute_exact_f_and_Tz_error,
m_point_count, NPARAMS, x,
NULL, NULL, NULL, NULL);
}
클래스 형태의 템플릿( CLmdif )으로 선언된 "lmdif"의 member function "Lmdif"를 호출할 때,
min/Lmdif.h:48
template<class T> class CLmdif : private CLmdif_
{
};
{
int Lmdif(T *p_user, bool (T::*p_func)(int m, int n, const double *parms, double *err),
int m, int n, double *x, double *fvec, double *diag, int *ipvt, double *qtf)
};
후자인 같은 member function, ncc_compute_exact_f_and_Tz_error()를 인자로 넣고 있고 (위 부분 코드들 중 오렌지 색 부분), 컴파일 하면 이 부분을 <unknown type>으로 인식하지 못 하겠다는 에러 메시지를 보낸다. 그리고 다음과 같은 형태를 추천한다고 한다.
note: candidates are: int CLmdif<T>::Lmdif(T*, bool (T::*)(int, int, const double*, double*), int, int, double*, double*, double*, int*, double*) [with T = CTsai]
function pointer의 형태가 틀린 모양인데, 오렌지색 부분을 그냥 함수가 아닌 어떤 class의 non-static member function을 가리키는 pointer로 &CTsai::ncc_compute_exact_f_and_Tz_error 이렇게 바꾸어 주면, 에러 메시지가 다음과 같이 바뀐다.
error: no matching function for call to 'CLmdif<CTsai>::Lmdif(CTsai* const, bool (*)(int, int, const double*, double*), int&, const int&, double [3], NULL, NULL, NULL, NULL)'
연두색 부분 대신 CTsai::ncc_compute_exact_f_and_Tz_error 이렇게 바꾸어 주면, 에러 메시지가 다음과 같다.
error: no matching function for call to 'CLmdif<CTsai>::Lmdif(CTsai* const, bool (&)(int, int, const double*, double*), int&, const int&, double [3], NULL, NULL, NULL, NULL)'
해결:
편법으로, class CLmdif를 클래스 형 템플릿이 아닌 그냥 클래스로 바꾸어서 선언하고 연두색 부분처럼 호출하면 에러는 안 나기에 일단 이렇게 넘어가기로 한다.
문제점#2.
코드에서 Windows OS 기반 MFC를 사용하고 있어 Mac OS X에서 에러가 난다.
해결:
MFC를 사용하는 "StdAfx.h"는 모두 주석 처리한다.
문제점#3.
Lmdif.h
... 기타 등등의 문제점들을 해결하고, 캘리브레이션을 수행한 결과가 맞는지 확인하자.
source code:
if (
CRimage.size() > 0 ) // if there is a valid point with its cross
ratio
{
correspondPoints(indexI, indexW, p, CRimage, linesYorder.size(), linesXorder.size(), world, CRworld, dxList.size(), dyList.size(), iplMatch, scale );
}
cvShowImage( "match", iplMatch );
cvSaveImage( "match.bmp", iplMatch );
cout << "# of pairs = " << indexI.size() << " = " << indexW.size() << endl;
// # 6. camera calibration
int numPair = indexI.size();
tsai.Clear();
for( int n = 0; n < numPair; n++ )
{
tsai.Point(world[indexW[n]].x, world[indexW[n]].y, world[indexW[n]].z, p[indexI[n]].x, p[indexI[n]].y);
cout << "pair #" << n << ": " << p[indexI[n]].x << " " << p[indexI[n]].y << " : "
<< world[indexW[n]].x << " " << world[indexW[n]].y << " " << world[indexW[n]].z << endl;
}
if( numPair < 8 )
cout << "Didn't get enough points" << endl;
if(!tsai.Compute())
cout << "Camera calibration failed" << endl;
cout << endl << "camera parameter" << endl
<< "focus = " << tsai.F() << endl
<< "principal axis (x,y) = " << tsai.Cx() << ", " << tsai.Cy() << endl
<< "kappa1 (lens distortion) = " << tsai.Kappa1() << endl
<< "skew_x = " << tsai.Sx() << endl;
// reproject world points on to the image frame to check the result of computing camera parameters
for(int n=0; n<tsai.PointCount(); n++)
{
double ux, uy;
tsai.WorldToImage (tsai.PointX(n), tsai.PointY(n), tsai.PointZ(n), ux, uy);
CvPoint reproj = cvPoint( cvRound(ux), cvRound(uy) );
cvCircle( iplInput, reproj, 3, CV_RGB(200,100,200), 2 );
}
{
correspondPoints(indexI, indexW, p, CRimage, linesYorder.size(), linesXorder.size(), world, CRworld, dxList.size(), dyList.size(), iplMatch, scale );
}
cvShowImage( "match", iplMatch );
cvSaveImage( "match.bmp", iplMatch );
cout << "# of pairs = " << indexI.size() << " = " << indexW.size() << endl;
// # 6. camera calibration
int numPair = indexI.size();
tsai.Clear();
for( int n = 0; n < numPair; n++ )
{
tsai.Point(world[indexW[n]].x, world[indexW[n]].y, world[indexW[n]].z, p[indexI[n]].x, p[indexI[n]].y);
cout << "pair #" << n << ": " << p[indexI[n]].x << " " << p[indexI[n]].y << " : "
<< world[indexW[n]].x << " " << world[indexW[n]].y << " " << world[indexW[n]].z << endl;
}
if( numPair < 8 )
cout << "Didn't get enough points" << endl;
if(!tsai.Compute())
cout << "Camera calibration failed" << endl;
cout << endl << "camera parameter" << endl
<< "focus = " << tsai.F() << endl
<< "principal axis (x,y) = " << tsai.Cx() << ", " << tsai.Cy() << endl
<< "kappa1 (lens distortion) = " << tsai.Kappa1() << endl
<< "skew_x = " << tsai.Sx() << endl;
// reproject world points on to the image frame to check the result of computing camera parameters
for(int n=0; n<tsai.PointCount(); n++)
{
double ux, uy;
tsai.WorldToImage (tsai.PointX(n), tsai.PointY(n), tsai.PointZ(n), ux, uy);
CvPoint reproj = cvPoint( cvRound(ux), cvRound(uy) );
cvCircle( iplInput, reproj, 3, CV_RGB(200,100,200), 2 );
}
// draw a cube on the image coordinate
computed by camera parameters according to the world coordinate
drawcube( tsai, iplInput, patSize );
cvShowImage( "input", iplInput );
cvShowImage( "input", iplInput );
아래 사진은 구해진 카메라 내부/외부 파라미터들을 가지고 (1) 실제 패턴의 점에 대응하는 이미지 프레임 (image coordinate) 상의 점을 찾아 (reprojection) 보라색 원으로 그리고, (2) 실제 패턴이 있는 좌표 (world coordinate)를 기준으로 한 graphic coordinate에 직육면체 cube를 노란색 선으로 그린 결과이다.
이미지 프레임과 실제 패턴 상의 점을 1 대 1로 비교하여 연결한 16쌍의 대응점 |
구한 카메라 파라미터를 가지고 실제 패턴 위의 점들을 이미지 프레임에 reproject한 결과 (보라색 점)와 실제 패턴의 좌표를 기준으로 한 그래픽이 이미지 프레임 상에 어떻게 나타나는지 그린 결과 (노란색 상자) |
위 왼쪽 사진에서 보여지는 16쌍의 대응점들의 좌표값을 "이미지 좌표(x,y) : 패턴 좌표 (x,y,z)"로 출력한 결과:
# of pairs = 16 = 16
pair #0: 7.81919 36.7864 : 119.45 82.8966 0
pair #1: 15.1452 71.2526 : 119.45 108.484 0
pair #2: 26.1296 122.93 : 119.45 147.129 0
pair #3: 36.6362 172.36 : 119.45 182.066 0
pair #4: 77.3832 20.4703 : 159.45 82.8966 0
pair #5: 85.4293 53.7288 : 159.45 108.484 0
pair #6: 97.8451 105.05 : 159.45 147.129 0
pair #7: 109.473 153.115 : 159.45 182.066 0
pair #8: 96.6046 15.962 : 171.309 82.8966 0
pair #9: 105.046 48.8378 : 171.309 108.484 0
pair #10: 118.177 99.9803 : 171.309 147.129 0
pair #11: 130.4 147.586 : 171.309 182.066 0
pair #12: 145.469 4.50092 : 199.965 82.8966 0
pair #13: 154.186 36.5857 : 199.965 108.484 0
pair #14: 168.033 87.5497 : 199.965 147.129 0
pair #15: 180.732 134.288 : 199.965 182.066 0
pair #0: 7.81919 36.7864 : 119.45 82.8966 0
pair #1: 15.1452 71.2526 : 119.45 108.484 0
pair #2: 26.1296 122.93 : 119.45 147.129 0
pair #3: 36.6362 172.36 : 119.45 182.066 0
pair #4: 77.3832 20.4703 : 159.45 82.8966 0
pair #5: 85.4293 53.7288 : 159.45 108.484 0
pair #6: 97.8451 105.05 : 159.45 147.129 0
pair #7: 109.473 153.115 : 159.45 182.066 0
pair #8: 96.6046 15.962 : 171.309 82.8966 0
pair #9: 105.046 48.8378 : 171.309 108.484 0
pair #10: 118.177 99.9803 : 171.309 147.129 0
pair #11: 130.4 147.586 : 171.309 182.066 0
pair #12: 145.469 4.50092 : 199.965 82.8966 0
pair #13: 154.186 36.5857 : 199.965 108.484 0
pair #14: 168.033 87.5497 : 199.965 147.129 0
pair #15: 180.732 134.288 : 199.965 182.066 0
그런데 위 오른쪽 사진에서 보여지는 결과는 이전 프레임에서 20쌍의 대응점으로부터 구한 카메라 파라미터 값을 가지고 계산한 결과이다.
# of found lines = 8 vertical, 7 horizontal
vertical lines:
horizontal lines:
p.size = 56
CRimage.size = 56
# of pairs = 20 = 20
pair #0: -42.2331 53.2782 : 102.07 108.484 0
pair #1: -22.6307 104.882 : 102.07 147.129 0
pair #2: -4.14939 153.534 : 102.07 182.066 0
pair #3: 1.81771 169.243 : 102.07 193.937 0
pair #4: -10.9062 41.1273 : 119.45 108.484 0
pair #5: 8.69616 92.7309 : 119.45 147.129 0
pair #6: 27.0108 140.945 : 119.45 182.066 0
pair #7: 32.9779 156.653 : 119.45 193.937 0
pair #8: 57.4164 14.6267 : 159.45 108.484 0
pair #9: 77.7374 65.9516 : 159.45 147.129 0
pair #10: 96.3391 112.934 : 159.45 182.066 0
pair #11: 102.524 128.555 : 159.45 193.937 0
pair #12: 76.5236 7.21549 : 171.309 108.484 0
pair #13: 97.5633 58.2616 : 171.309 147.129 0
pair #14: 116.706 104.705 : 171.309 182.066 0
pair #15: 123.108 120.238 : 171.309 193.937 0
pair #16: 125.015 -11.5931 : 199.965 108.484 0
pair #17: 146.055 39.453 : 199.965 147.129 0
pair #18: 164.921 85.2254 : 199.965 182.066 0
pair #19: 171.323 100.758 : 199.965 193.937 0
camera parameter
focus = 3724.66
principal axis (x,y) = 168.216, 66.5731
kappa1 (lens distortion) = -6.19473e-07
skew_x = 1
vertical lines:
horizontal lines:
p.size = 56
CRimage.size = 56
# of pairs = 20 = 20
pair #0: -42.2331 53.2782 : 102.07 108.484 0
pair #1: -22.6307 104.882 : 102.07 147.129 0
pair #2: -4.14939 153.534 : 102.07 182.066 0
pair #3: 1.81771 169.243 : 102.07 193.937 0
pair #4: -10.9062 41.1273 : 119.45 108.484 0
pair #5: 8.69616 92.7309 : 119.45 147.129 0
pair #6: 27.0108 140.945 : 119.45 182.066 0
pair #7: 32.9779 156.653 : 119.45 193.937 0
pair #8: 57.4164 14.6267 : 159.45 108.484 0
pair #9: 77.7374 65.9516 : 159.45 147.129 0
pair #10: 96.3391 112.934 : 159.45 182.066 0
pair #11: 102.524 128.555 : 159.45 193.937 0
pair #12: 76.5236 7.21549 : 171.309 108.484 0
pair #13: 97.5633 58.2616 : 171.309 147.129 0
pair #14: 116.706 104.705 : 171.309 182.066 0
pair #15: 123.108 120.238 : 171.309 193.937 0
pair #16: 125.015 -11.5931 : 199.965 108.484 0
pair #17: 146.055 39.453 : 199.965 147.129 0
pair #18: 164.921 85.2254 : 199.965 182.066 0
pair #19: 171.323 100.758 : 199.965 193.937 0
camera parameter
focus = 3724.66
principal axis (x,y) = 168.216, 66.5731
kappa1 (lens distortion) = -6.19473e-07
skew_x = 1
대응점 연결에 오차가 없으면, 즉, 패턴 인식이 잘 되면, Tsai 알고리즘에 의한 카메라 파라미터 구하기가 제대로 되고 있음을 확인할 수 있다. 하지만, 현재 full optimization (모든 파라미터들에 대해 최적화 과정을 수행하는 것)으로 동작하게 되어 있고, 프레임마다 모든 파라미터들을 새로 구하고 있기 때문에, 속도가 매우 느리다. 시험 삼아 reprojection과 간단한 graphic을 그리는 과정은 속도에 큰 영향이 없지만, 그전에 카메라 캘리브레이션을 하는 데 필요한 계산 시간이 길다. 입력 프레임이 들어오는 시간보다 훨씬 많은 시간이 걸려 실시간 구현이 되지 못 하고 있다.
따라서, (1) 내부 파라미터는 첫 프레임에서 한 번만 계산하고 (2) 이후 매 프레임마다 외부 파라미터 (카메라의 회전과 이동)만을 따로 계산하는 것으로 코드를 수정해야 한다.
Try#3.
OpenCV 함수 이용
1) 내부 파라미터 계산
cvCalibrateCamera2
2) lens distortion(kappa1, kappa2)을 가지고 rectification
cvInitUndistortRectifyMap
3) line detection
4) 패턴 인식 (대응점 찾기)
5) 외부 파라미터 계산 (4의 결과 & lens distortion = 0 입력)
cvFindExtrinsicCameraParams2
6) reprojection
2)에서 얻은 rectificated image에 할 것
'Computer Vision' 카테고리의 다른 글
virtual studio 구현: camera calibration (0) | 2010.05.26 |
---|---|
Jonathan Merritt's Camera Calibration for Blender (0) | 2010.05.18 |
virtual studio 구현: feature points matching test (0) | 2010.05.14 |
Rahbar, K. & Pourreza, H. R "Inside looking out camera pose estimation for virtual studio" (0) | 2010.04.28 |
virtual studio 구현: pattern design (0) | 2010.04.27 |