1. 程式人生 > >相機標定過程

相機標定過程

機器視覺

1. 攝像機標定的數學過程如下:

技術分享

這裏程序的實現是在opencv中,所以就用opencv的程序來說明具體的過程.註意各個版本的opencv之間的程序移植性並不好,以下程序是在opencv2.4.3下編制運行的,

註意

1.程序運行前需要插上攝像頭,否則程序有可能不能正常運行


2.獲取棋盤格圖像

張正友論文中建議棋盤格數大於7*7,棋盤格在圖像中所占面積在50%以上,其實這裏是有問題的,因為原來遇到過球面相機將棋盤格放置大於50%以上反而出問題,這裏還沒有弄清楚怎麽回事,所以以下的標定都是針對非球面相機的.

for (int i=1; i<=19; i++)//輸入左標定板圖像
{
std::stringstream str;//聲明輸入輸出流
str << "./left" << i << ".jpg";//以名字方式把圖像輸入到流
std::cout << str.str() << std::endl;//.str("")清除內容 .clear()清空標記位

leftFileList.push_back(str.str());//.push_back從容器後向前插入數據
leftBoardImage = cv::imread(str.str(),0);//用來顯示即時輸入的圖像
cv::namedWindow("left chessboard image");
cv::imshow("left chessboard image",leftBoardImage);
cv::waitKey(10);
}


3.定義棋盤格的角點數目

cv::Size boardSize(14,10)


4.程序定位提取角點

這裏建立的是世界坐標系(三維)和圖像坐標系(二維)之間的關系

(1)首先聲明兩個坐標容器

std::vector<cv::Point2f> imageCorners;//二位坐標點
std::vector<cv::Point3f> objectCorners;//三維坐標點

(2)初始化棋盤角點,令其位置位於(x,y,z)=(i,j,0),一個棋盤格為一個坐標值

for (int i=0; i<boardSize.height; i++)
{
for (int j=0; j<boardSize.width; j++)
{
objectCorners.push_back(cv::Point3f(i, j, 0.0f));
}
}

(3)直接使用opencv內函數找到二維角點坐標,並建立標定標定格子和實際坐標間的關系(像素級別)

這個函數使用時,當標定板是長方形時可以找到角點,但是標定板是正方形時,就找不到,原因還未知

cv::findChessboardCorners(image, boardSize, imageCorners);

(4)獲得像素精度往往是不夠的,還需要獲得亞像素的精度

cv::cornerSubPix(image,
imageCorners,
cv::Size(5,5),//搜索框的一半,表示在多大窗口定位角點
cv::Size(-1,-1), //死區
cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
30, // max number of iterations//叠代最大次數
0.01)); // min accuracy//最小精度

相機標定過程