Opencv摄像头标定(参数+校正),但cvFindChessboardCorners不太稳定,必须标版
#include <cv.h> #include <highgui.h> #include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std; int n_boards=0;//图像数目 canshu const int board_dt=20;//等20帧每棋盘视图 xin //int sn_board=0;//成功找到角点的图像数目 int board_w;//图像的角点行列数 canshu int board_h; //canshu int main(int argc ,char * argv[]) { /*读入图像*/ CvCapture*capture; //xin if(argc!=4)//xin { printf("ERROR:Wrong number of input parameters\n");//xin return -1; //xin } board_w=atoi(argv[1]); //canshu board_h=atoi(argv[2]); //canshu n_boards=atoi(argv[3]); //canshu int board_n=board_h*board_w;//每幅图像的角点数 CvSize board_size=cvSize(board_w,board_h);//每幅图像的角点数 capture=cvCreateCameraCapture(0);//xin //assert(capture); //xin if(!capture) { printf("\nCouldn‘t open the camera\n"); return -1;} cvNamedWindow("MyCalib"); cvNamedWindow("Raw Video"); //allocate storage CvMat*object_points = cvCreateMat(board_n*n_boards,3,CV_32FC1); CvMat*image_points =cvCreateMat(board_n*n_boards,2,CV_32FC1); CvMat*point_counts =cvCreateMat(n_boards,1,CV_32SC1); CvMat * camera_matrix =cvCreateMat(3,3,CV_32FC1);//摄像机矩阵(内参数矩阵) 分配矩阵空间(行,列,类型)类型为矩阵元素类型 CvMat * distortion_coeffs=cvCreateMat(4,1,CV_32FC1);//畸变系数 CvPoint2D32f*corners=new CvPoint2D32f[board_n];//一幅图像的角点数组 int corner_count; int successes=0; //xin// 本文 successes就是 sn_board int step,frame=0; //xin IplImage*image=cvQueryFrame(capture); //图像的大小 // xin IplImage *gray_image=cvCreateImage(cvGetSize(image),8,1);//创建头并分配数据//tong SourceImgGray //亚像素subpixel //capture corner views loop until we‘ve got n_boards //成功捕获(找到所有角点on the board) while (successes<n_boards) { //skip every board_dt frames to allow user to move chessboard if(frame++%board_dt==0) { int found=cvFindChessboardCorners(image,board_size,corners,&corner_count,CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS); //精确到亚像素 cvCvtColor(image,gray_image,CV_BGR2GRAY); //xin cvFindCornerSubPix(image,corners,corner_count,cvSize(15,15),cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1)); cvDrawChessboardCorners(image,board_size,corners,corner_count,found); //绘制棋盘角点。found //cvShowImage("MyCalib",image); //如果得到一个好板,则把把它加入到我们的数据中 if(corner_count==board_n){ //xin cvShowImage( "Calibration", image ); //show in color if we did collect the image step=successes*board_n; //xin for(int i=step,j=0;j<board_n;++i,++j){ //xinjia canshu i CV_MAT_ELEM(*image_points,float,i,0) =corners[j].x;//CV_MAT_ELEM用来访问矩阵每个元素的宏,这个宏只对单通道矩阵有效,多通道会报错 CV_MAT_ELEM(*image_points,float,i,1) =corners[j].y;//(要访问的矩阵,矩阵元素的类型,所要访问元素的行数,列数) //上两句是将检测到的点以坐标形式存储 CV_MAT_ELEM(*object_points,float,i,0) =float(j/board_w); CV_MAT_ELEM(*object_points,float,i,1) =float(j%board_w); //上两句是将检测到的点的数目,以行列形式存储 CV_MAT_ELEM(*object_points,float,i,2) =0.0f; } CV_MAT_ELEM(*point_counts,int,successes,0)=board_n; successes++; printf("Collected our %d of %d needed chessboard images\n",successes,n_boards); } else cvShowImage( "Calibration", gray_image );//Show Gray if we didn‘t collect the image }//end skip board_dt between chessboard capture //暂停模块handle pause/unpause and ESC //xin int c = cvWaitKey(15); if(c == ‘p‘){ c = 0; while(c != ‘p‘ && c != 27){ c = cvWaitKey(250); } } if(c == 27) return 0; image = cvQueryFrame( capture ); //Get next image cvShowImage("Raw Video", image); } //END COLLECTION WHILE LOOP. cvDestroyWindow("Calibration"); printf("\n\n*** CALLIBRATING THE CAMERA..."); //重新赋值,又重新分配了矩阵空间 CvMat * object_points0= cvCreateMat(board_n*successes,3,CV_32FC1); CvMat * image_points0=cvCreateMat(board_n*successes,2,CV_32FC1); CvMat * point_counts0=cvCreateMat(successes,1,CV_32SC1); //transfer THE points INTO THE correct size matrices for (int i=0;i<successes*board_n;i++)//board_n为每幅图像的角点数*sn_board为成功找到角点的图像数目 { CV_MAT_ELEM(*image_points0,float,i,0)=CV_MAT_ELEM(*image_points,float,i,0); CV_MAT_ELEM(*image_points0,float,i,1)=CV_MAT_ELEM(*image_points,float,i,1); CV_MAT_ELEM(*object_points0,float,i,0)=CV_MAT_ELEM(*object_points,float,i,0); CV_MAT_ELEM(*object_points0,float,i,1)=CV_MAT_ELEM(*object_points,float,i,1); CV_MAT_ELEM(*object_points0,float,i,2)=0.0f; } for (int i=0;i<successes;i++) { CV_MAT_ELEM(*point_counts0,int,i,0)=CV_MAT_ELEM(*point_counts,int,i,0); } cvReleaseMat(&object_points);//世界坐标点 cvReleaseMat(&point_counts); //每张图像中的角点数 cvReleaseMat(&image_points); //图像坐标点 //使用cvReleaseMat函数之后,系统将释放刚才载入矩阵的内存空间(也即这个矩阵已经不在内存中了) // At this point we have all of the chessboard corners we need. // Initialize the intrinsic matrix such that the two focal // lengths have a ratio of 1.0 // CV_MAT_ELEM( *camera_matrix, float, 0, 0 ) = 1.0f; // xin CV_MAT_ELEM( *camera_matrix, float, 1, 1 ) = 1.0f; //xin //CALIBRATE THE CAMERA! cvCalibrateCamera2( //xin object_points0, image_points0, //xin point_counts0, cvGetSize( image ), camera_matrix, distortion_coeffs, NULL, NULL,0 //CV_CALIB_FIX_ASPECT_RATIO ); // SAVE THE INTRINSICS AND DISTORTIONS xin printf("......保存内部参数与畸变参数\n"); cvSave("camera_matrix1111.xml",camera_matrix); cvSave("distortion_coeffs.xml",distortion_coeffs); // EXAMPLE OF LOADING THESE MATRICES BACK IN: xin CvMat *intrinsic = (CvMat*)cvLoad("Intrinsics.xml"); CvMat *distortion = (CvMat*)cvLoad("Distortion.xml"); // Build the undistort map which we will use for all // subsequent frames.建立不失真的图map // IplImage* mapx = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 ); IplImage* mapy = cvCreateImage( cvGetSize(image), IPL_DEPTH_32F, 1 ); cvInitUndistortMap(intrinsic,distortion,mapx, mapy); // Just run the camera to the screen, now showing the raw and // the undistorted image. // cvNamedWindow( "Undistort" ); while(image) { IplImage *t = cvCloneImage(image); cvShowImage( "Raw Video", image ); // Show raw image cvRemap( t, image, mapx, mapy ); // Undistort image cvReleaseImage(&t); cvShowImage("Undistort", image); // Show corrected image //Handle pause/unpause and ESC int c = cvWaitKey(15); if(c == ‘p‘){ c = 0; while(c != ‘p‘ && c != 27){ c = cvWaitKey(250); } } if(c == 27) break; image = cvQueryFrame( capture ); } return 0; }
文章来自:http://www.cnblogs.com/sjxiaoe/p/5034421.html