OpenCV sample目錄下自帶兩個與相機標定的cpp文件即:calibration.cpp和calibration_artificial.cpp
calibration.cpp 是通過用戶輸入可選參數(shù)進行攝像機標定的程序。
calibration_artificial.cpp 是程序模擬模擬攝像機標定的過程,即程序創(chuàng)建棋盤然后自主標定。
通常我們有兩種方式去標定,一個是實時的從攝像機獲取拍攝到的棋盤進行標定,一個是已經(jīng)獲得了一些棋盤的圖片來標定。
本文詳細介紹第二種,即用已獲得的棋盤圖片的整個過程。
方法一:編譯生成 .exe文件,然后在commond 窗口輸入?yún)?shù)執(zhí)行
方法二:通過添加輸入?yún)?shù)的代碼,然后執(zhí)行(可以單步調(diào)試)(推薦此方法)
calibration.cpp 和 calibration_artificial.cpp 位置如圖所示。此外,棋盤圖片也在同一目錄下
找到文件后,開始新建工程吧。不過在用以獲得的圖像來進行標定,應(yīng)先通過OpenCV自帶的imagelist_creator.cpp 產(chǎn)生一個xml或者yaml格式的圖像列表,然后在使用下面的程序。
第一步,新建項目demo,添加剛才那個目錄下的imagelist_creator.cpp 編譯執(zhí)行得到可執(zhí)行文件 demo.exe
第二步,執(zhí)行demo.exe 產(chǎn)生一個xml或者yaml格式的圖像列表
static void help(char** av)
{
cout 《《 “\nThis creates a yaml or xml list of files from the command line args\n”
“usage:\n./” 《《 av[0] 《《 “ imagelist.yaml *.png\n”
《《 “Try using different extensions.(e.g. yaml yml xml xml.gz etc.。。)\n”
《《 “This will serialize this list of images or whatever with opencv‘s FileStorage framework” 《《 endl;
}
輸入命令:demo imagelist.yaml left01.jpg left02.jpg left03.jpg left04.jpg left05.jpg left06.jpg left07.jpg left08.jpg left09.jpg left010.jpg left11.jpg left12.jpg left13.jpg left14.jpg right01.jpg right02.jpg right03.jpg right04.jpg right05.jpg right06.jpg right07.jpg right08.jpg right09.jpg right10.jpg right11.jpg right12.jpg right13.jpg right14.jpg 。回車,生成imagelist.yaml
第三步,進行相機的標定
先把14張棋盤圖片放到debug目錄下,然后移除imagelist_creator.cpp 添加 calibration.cpp ,如圖所示
編譯執(zhí)行,得到新的demo.exe ,進入cmd ,輸入 demo -w 6 -h 9 imagelist.yaml 回車即可。如圖所示,開始對每張圖片進行角點檢測
最后,得到一個 out_camera_data.yml 文件
內(nèi)容如下:
%YAML:1.0
calibration_time: “08/21/15 16:54:26”
image_width: 640
image_height: 480
board_width: 6
board_height: 9
square_size: 1.
flags: 0
camera_matrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 5.3765976500165073e+002, 0., 3.4011155767874686e+002, 0.,
5.3789341813113867e+002, 2.3694081464807104e+002, 0., 0., 1. ]
distortion_coefficients: !!opencv-matrix
rows: 5
cols: 1
dt: d
data: [ -2.7762353155161251e-001, 5.3976467600878486e-002,
2.1257384355991209e-003, -3.9487502777272009e-004,
4.8679847473271927e-002 ]
avg_reprojection_error: 4.4034956116049290e-001
此時,大功告成 =。=
//對于想自己單步調(diào)試的親,補充第二種方法,即通過添加代碼調(diào)試。
第一步:將圖片及imagelist放到 D:\Workspace\demo\demo目錄下
第二步: 添加代碼
具體過程如圖所示:
在該目錄下放入imagelist.yaml 和14張圖片
添加代碼
argc = 6;
argv[0] = “demo.exe”;
argv[1] = “-w”;
argv[2] = “6”;
argv[3] = “-h”;
argv[4] = “9”;
argv[5] = “imagelist.yaml”;
代碼
#include “stdafx.h”
#include “cv.h”
#include “highgui.h”
#include 《string》
#include 《iostream》
using namespace std;
int main()
{
int cube_length=7;
CvCapture* capture;
capture=cvCreateCameraCapture(0);
if(capture==0){
printf(“無法捕獲攝像頭設(shè)備!\n\n”);
return 0;
}else{
printf(“捕獲攝像頭設(shè)備成功!!\n\n”);
}
IplImage* frame;
cvNamedWindow(“攝像機幀截取窗口”,1);
printf(“按“C”鍵截取當前幀并保存為標定圖片。。。\n按“Q”鍵退出截取幀過程。。。\n\n”);
int number_image=1;
char *str1;
str1=“.jpg”;
char filename[20]=“”;
while(true)
{
frame=cvQueryFrame(capture);
if(!frame)
break;
cvShowImage(“攝像機幀截取窗口”,frame);
if(cvWaitKey(10)==‘c’){
sprintf_s (filename,“%d.jpg”,number_image);
cvSaveImage(filename,frame);
cout《《“成功獲取當前幀,并以文件名”《《filename《《“保存。。。\n\n”;
printf(“按“C”鍵截取當前幀并保存為標定圖片。。。\n按“Q”鍵退出截取幀過程。。。\n\n”);
number_image++;
}else if(cvWaitKey(10)==‘q’){
printf(“截取圖像幀過程完成。。。\n\n”);
cout《《“共成功截取”《《--number_image《《“幀圖像!!\n\n”;
break;
}
}
cvReleaseImage(&frame);
cvDestroyWindow(“攝像機幀截取窗口”);
IplImage * show;
cvNamedWindow(“RePlay”,1);
int a=1;
int number_image_copy=number_image;
CvSize board_size=cvSize(7,7);
int board_width=board_size.width;
int board_height=board_size.height;
int total_per_image=board_width*board_height;
CvPoint2D32f * image_points_buf = new CvPoint2D32f[total_per_image];
CvMat * image_points=cvCreateMat(number_image*total_per_image,2,CV_32FC1);
CvMat * object_points=cvCreateMat(number_image*total_per_image,3,CV_32FC1);
CvMat * point_counts=cvCreateMat(number_image,1,CV_32SC1);
CvMat * intrinsic_matrix=cvCreateMat(3,3,CV_32FC1);
CvMat * distortion_coeffs=cvCreateMat(5,1,CV_32FC1);
int count;
int found;
int step;
int successes=0;
while(a《=number_image_copy){
sprintf_s (filename,“%d.jpg”,a);
show=cvLoadImage(filename,-1);
found=cvFindChessboardCorners(show,board_size,image_points_buf,&count,
CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
if(found==0){
cout《《“第”《《a《《“幀圖片無法找到棋盤格所有角點!\n\n”;
cvNamedWindow(“RePlay”,1);
cvShowImage(“RePlay”,show);
cvWaitKey(0);
}else{
cout《《“第”《《a《《“幀圖像成功獲得”《《count《《“個角點。。。\n”;
cvNamedWindow(“RePlay”,1);
IplImage * gray_image= cvCreateImage(cvGetSize(show),8,1);
cvCvtColor(show,gray_image,CV_BGR2GRAY);
cout《《“獲取源圖像灰度圖過程完成。。。\n”;
cvFindCornerSubPix(gray_image,image_points_buf,count,cvSize(11,11),cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1));
cout《《“灰度圖亞像素化過程完成。。。\n”;
cvDrawChessboardCorners(show,board_size,image_points_buf,count,found);
cout《《“在源圖像上繪制角點過程完成。。。\n\n”;
cvShowImage(“RePlay”,show);
cvWaitKey(0);
}
if(total_per_image==count){
step=successes*total_per_image;
for(int i=step,j=0;j《total_per_image;++i,++j){
CV_MAT_ELEM(*image_points,float,i,0)=image_points_buf[j].x;
CV_MAT_ELEM(*image_points,float,i,1)=image_points_buf[j].y;
CV_MAT_ELEM(*object_points,float,i,0)=(float)(j/cube_length);
CV_MAT_ELEM(*object_points,float,i,1)=(float)(j%cube_length);
CV_MAT_ELEM(*object_points,float,i,2)=0.0f;
}
CV_MAT_ELEM(*point_counts,int,successes,0)=total_per_image;
successes++;
}
a++;
}
cvReleaseImage(&show);
cvDestroyWindow(“RePlay”);
cout《《“*********************************************\n”;
cout《《number_image《《“幀圖片中,標定成功的圖片為”《《successes《《“幀。。。\n”;
cout《《number_image《《“幀圖片中,標定失敗的圖片為”《《number_image-successes《《“幀。。。\n\n”;
cout《《“*********************************************\n\n”;
cout《《“按任意鍵開始計算攝像機內(nèi)參數(shù)。。。\n\n”;
CvCapture* capture1;
capture1=cvCreateCameraCapture(0);
IplImage * show_colie;
show_colie=cvQueryFrame(capture1);
CvMat * object_points2=cvCreateMat(successes*total_per_image,3,CV_32FC1);
CvMat * image_points2=cvCreateMat(successes*total_per_image,2,CV_32FC1);
CvMat * point_counts2=cvCreateMat(successes,1,CV_32SC1);
for(int i=0;i《successes*total_per_image;++i){
CV_MAT_ELEM(*image_points2,float,i,0)=CV_MAT_ELEM(*image_points,float,i,0);
CV_MAT_ELEM(*image_points2,float,i,1)=CV_MAT_ELEM(*image_points,float,i,1);
CV_MAT_ELEM(*object_points2,float,i,0)=CV_MAT_ELEM(*object_points,float,i,0);
CV_MAT_ELEM(*object_points2,float,i,1)=CV_MAT_ELEM(*object_points,float,i,1);
CV_MAT_ELEM(*object_points2,float,i,2)=CV_MAT_ELEM(*object_points,float,i,2);
}
for(int i=0;i《successes;++i){
CV_MAT_ELEM(*point_counts2,int,i,0)=CV_MAT_ELEM(*point_counts,int,i,0);
}
cvReleaseMat(&object_points);
cvReleaseMat(&image_points);
cvReleaseMat(&point_counts);
CV_MAT_ELEM(*intrinsic_matrix,float,0,0)=1.0f;
CV_MAT_ELEM(*intrinsic_matrix,float,1,1)=1.0f;
cvCalibrateCamera2(object_points2,image_points2,point_counts2,cvGetSize(show_colie),
intrinsic_matrix,distortion_coeffs,NULL,NULL,0);
cout《《“攝像機內(nèi)參數(shù)矩陣為:\n”;
cout《《CV_MAT_ELEM(*intrinsic_matrix,float,0,0)《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,0,1)
《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,0,2)
《《“\n\n”;
cout《《CV_MAT_ELEM(*intrinsic_matrix,float,1,0)《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,1,1)
《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,1,2)
《《“\n\n”;
cout《《CV_MAT_ELEM(*intrinsic_matrix,float,2,0)《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,2,1)
《《“ ”《《CV_MAT_ELEM(*intrinsic_matrix,float,2,2)
《《“\n\n”;
cout《《“畸變系數(shù)矩陣為:\n”;
cout《《CV_MAT_ELEM(*distortion_coeffs,float,0,0)《《“ ”《《CV_MAT_ELEM(*distortion_coeffs,float,1,0)
《《“ ”《《CV_MAT_ELEM(*distortion_coeffs,float,2,0)
《《“ ”《《CV_MAT_ELEM(*distortion_coeffs,float,3,0)
《《“ ”《《CV_MAT_ELEM(*distortion_coeffs,float,4,0)
《《“\n\n”;
cvSave(“Intrinsics.xml”,intrinsic_matrix);
cvSave(“Distortion.xml”,distortion_coeffs);
cout《《“攝像機矩陣、畸變系數(shù)向量已經(jīng)分別存儲在名為Intrinsics.xml、Distortion.xml文檔中\(zhòng)n\n”;
CvMat * intrinsic=(CvMat *)cvLoad(“Intrinsics.xml”);
CvMat * distortion=(CvMat *)cvLoad(“Distortion.xml”);
IplImage * mapx=cvCreateImage(cvGetSize(show_colie),IPL_DEPTH_32F,1);
IplImage * mapy=cvCreateImage(cvGetSize(show_colie),IPL_DEPTH_32F,1);
cvInitUndistortMap(intrinsic,distortion,mapx,mapy);
cvNamedWindow(“原始圖像”,1);
cvNamedWindow(“非畸變圖像”,1);
cout《《“按‘E’鍵退出顯示。。。\n\n”;
while(show_colie){
IplImage * clone=cvCloneImage(show_colie);
cvShowImage(“原始圖像”,show_colie);
cvRemap(clone,show_colie,mapx,mapy);
cvReleaseImage(&clone);
cvShowImage(“非畸變圖像”,show_colie);
if(cvWaitKey(10)==‘e’){
break;
}
show_colie=cvQueryFrame(capture1);
}
return 0;
}
評論
查看更多