这个是我在win32 平台下写的程序,测试完全通过:不过要注意下面的问题:(1)opencv库是1.0的,我在vc6.0的平台使用(2)软件的设置要正确(3)图片载入的时候,使用的是批处理文件(其实就是建一个txt文件,里面写的和dos下面的操作代码一样的输入)(4)里面现在还有个问题没有解决:在得到角点坐标的时候,cvFindCornerSubPix里面的搜索区域还不明白(05)下面是我在网上搜的别人的代:测试通过的:
http://www.china-vision.net/blog/user2/29043/2009331171717.html
下面是我的代码:/*标定的过程: 图片的加载 角点的检测 提取角点精确坐标 参数求解 利用参数对图像进行矫正*/#i nclude<stdio.h>#i nclude"cv.h"#i nclude"highgui.h"#i nclude <stdlib.h> //函数声明void PrintMat(CvMat *matrix,BOOL save_or_show,FILE *fp);int main(int argc,char **argv){ int i=1; char k=0; int CurrentImage = 0; int CurrentRow = 0; //行 int CurrentColumn = 0; //列 int findcorner_result=0; FILE *fp; //文件指针 int ChessBoardSize_w =6; //角点个数 int ChessBoardSize_h =7; int width_pixel =1280; //像素 int high_pixel =1024; float SquareSize=10; //棋盘大小 int NImages=16; CvSize ChessBoardSize; CvSize image_pixel; int NPoints=0; int *corner_counter; float *temppoints; //这里可以使用内存动态存储管理。。。 CvPoint2D32f *corners; //存储角点坐标的数组 //单通道灰度图像 IplImage *grayimage=0; IplImage *srcimage=0; //三通道图像 IplImage *result_image=0; //矫正以后的图像 CvMat *intrinsic_matrix=0; //内部参数矩阵 CvMat *distortion_coeffs=0; //畸变系数 CvMat *rotation_vectors=0; //旋转向量 CvMat *translation_vectors=0;//平移向量 CvMat *points_counts=0; //图片角点数 CvMat *object_points=0; //世界坐标系中角点的坐标 CvMat *image_points=0; //检测到的角点坐标 CvMat *temp_matrix,*rotation_matrix,*translation_matrix; //***************************************************** //数据载入、开辟空间 image_pixel = cvSize(width_pixel,high_pixel); ChessBoardSize = cvSize(ChessBoardSize_w,ChessBoardSize_h); NPoints = ChessBoardSize_w*ChessBoardSize_h; corner_counter=calloc(NImages,sizeof(int)); //动态管理,记着释放空间 temppoints =calloc(NImages*NPoints*3,sizeof(float)); corners =calloc(NImages*NPoints,sizeof(CvPoint2D32f)); if((corner_counter==0 )||(temppoints==0 )||( corners==0 ) ) { return -1; } intrinsic_matrix = cvCreateMat(3,3,CV_32FC1); //内参数矩阵 distortion_coeffs = cvCreateMat(1,4,CV_32FC1); //形变参数 rotation_vectors = cvCreateMat(NImages,3,CV_32FC1); //旋转向量 translation_vectors = cvCreateMat(NImages,3,CV_32FC1); //平移向量 points_counts = cvCreateMat(NImages,1,CV_32SC1); //视图数目 object_points = cvCreateMat(NImages*NPoints,3,CV_32FC1);//世界坐标系中角点的坐标 image_points = cvCreateMat(NImages*NPoints,2,CV_32FC1);//检测到的坐标点坐标 temp_matrix= cvCreateMat(1,3,CV_32FC1); rotation_matrix = cvCreateMat(3,3,CV_32FC1); //旋转矩阵 translation_matrix = cvCreateMat(3,3,CV_32FC1); //旋转矩阵 grayimage=cvCreateImage(image_pixel,IPL_DEPTH_8U,1); //单通道灰度图像 result_image=cvCreateImage(image_pixel,IPL_DEPTH_8U,1); //校正以后的图像 fp = fopen( "data1.txt", "w+" ); //打开文件,建立一个文件,然后写入数据 fprintf(fp, "坐标数据:/n" ); //写入数据,写入文件 //**************************************************** //图片的加载以及角点的提取 if(argc!=NImages+1) { printf("图片加载有误!"); return -1; } for(CurrentImage=0;CurrentImage<NImages;CurrentImage++) { //加载图片 if((srcimage=cvLoadImage(argv[CurrentImage+1],1))!=0) { //色彩转换 cvCvtColor(srcimage,grayimage,CV_BGR2GRAY); //角点检测 findcorner_result=cvFindChessboardCorners(grayimage,ChessBoardSize,&corners[CurrentImage*NPoints], &corner_counter[CurrentImage],CV_CALIB_CB_ADAPTIVE_THRESH); //画出检测到的点 cvDrawChessboardCorners(srcimage,ChessBoardSize, &corners[CurrentImage*NPoints],corner_counter[CurrentImage],findcorner_result); //精确坐标位置 cvFindCornerSubPix(grayimage,&corners[CurrentImage*NPoints],corner_counter[CurrentImage], cvSize(10,10), cvSize(-1,-1),//这个搜索的范围。。。? cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,500,0.003)//迭代终止条件 ); cvNamedWindow("image",1); cvShowImage("image",srcimage); printf("检测到的角点:%d/n",corner_counter[CurrentImage]); //fprintf(fp,"检测到的角点:%d/n",corner_counter[CurrentImage]); //for(i=0;i<corner_counter[CurrentImage];i++)//坐标输出 // { // printf("第%d个角点 %f %f/n",i,corners[CurrentImage*NPoints+i].x,corners[CurrentImage*NPoints+i].y); //} cvWaitKey(0); printf("按任意键提取下一幅图片角点。。。/n"); //fprintf(fp,"按任意键提取下一幅图片角点。。。/n"); } } printf("角点提取结束....../n"); printf("开始定标....../n"); fprintf(fp,"角点提取结束....../n"); fprintf(fp,"开始定标....../n"); //棋盘世界坐标系坐标 for(CurrentImage = 0 ; CurrentImage < NImages ; CurrentImage++)//图片 { for (CurrentRow = 0; CurrentRow < ChessBoardSize_h; CurrentRow++)//行 { for (CurrentColumn = 0; CurrentColumn < ChessBoardSize_w; CurrentColumn++)//列 { temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3]=(float)(CurrentRow*SquareSize); temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3+1]=(float)(CurrentColumn*SquareSize); temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3+2]=0; } } } //参数求解 *object_points=cvMat(NImages*NPoints,3,CV_32FC1,temppoints);//似乎这里开始有点问题。。。还有就是在标定过程中这个棋盘的边长和标定的精度无关 cvSetData(image_points,corners,sizeof(CvPoint2D32f));//设置image_points矩阵的数据 cvSetData(points_counts,corner_counter,sizeof(int)); /*printf("棋盘坐标"); printf("/n"); PrintMat(object_points); printf("/n计算机/n"); printf("/n"); PrintMat(image_points); printf("/n"); printf("/n角点个数/n"); PrintMat(points_counts); printf("/n");*/ cvCalibrateCamera2(object_points,image_points,points_counts,cvGetSize(grayimage), intrinsic_matrix,distortion_coeffs,rotation_vectors, translation_vectors,0 ); printf("/n内部岑数矩阵/n"); fprintf(fp,"/n内部岑数矩阵/n"); PrintMat(intrinsic_matrix,FALSE,NULL); PrintMat(intrinsic_matrix,TRUE,fp); printf("/n形变岑数/n"); fprintf(fp,"/n形变岑数/n"); PrintMat(distortion_coeffs,FALSE,NULL); PrintMat(distortion_coeffs,TRUE,fp); for(i=0;i<NImages;i++) { cvGetRow(rotation_vectors,temp_matrix,i); cvRodrigues2(temp_matrix,rotation_matrix,0); printf(" 第%d个图片的旋转向量/n",i); fprintf(fp," 第%d个图片的旋转向量/n",i); PrintMat(temp_matrix,FALSE,NULL); PrintMat(temp_matrix,TRUE,fp); printf(" 第%d个图片的旋转矩阵/n",i); fprintf(fp," 第%d个图片的旋转矩阵/n",i); PrintMat(rotation_matrix,FALSE,NULL); PrintMat(rotation_matrix,TRUE,fp); printf("/n"); fprintf(fp,"/n"); } //cvReleaseMat(&temp_matrix); printf("平移矩阵/n"); fprintf(fp,"平移矩阵/n"); for(i=0;i<NImages;i++) { cvGetRow(translation_vectors,temp_matrix,i); cvRodrigues2(temp_matrix,translation_matrix,0); printf(" 第%d个图片的平移向量/n",i); fprintf(fp," 第%d个图片的平移向量/n",i); PrintMat(temp_matrix,FALSE,NULL); PrintMat(temp_matrix,TRUE,fp); printf(" 第%d个图片的平移矩阵/n",i); fprintf(fp," 第%d个图片的平移矩阵/n",i); PrintMat(translation_matrix,FALSE,NULL); PrintMat(translation_matrix,TRUE,fp); printf("/n"); fprintf(fp,"/n"); } // PrintMat(translation_vectors,FALSE,NULL); // PrintMat(translation_vectors,TRUE,fp); printf("标定结束...../n"); fprintf(fp,"标定结束...../n"); printf("按任意键开始误差分析...../n"); fprintf(fp,"按任意键开始误差分析...../n"); cvWaitKey(0); //误差分析 //利用已知的内部参数,使用cvProjectPoints2()计算出世界坐标系中的坐标在图片中的坐标也就是校准后的坐标 //将校准后的坐标和原来求得的坐标进行比较 for(CurrentImage=0;CurrentImage<NImages;CurrentImage++) { CvMat *object_matrix= cvCreateMat(NPoints,3,CV_32FC1); CvMat *image_matrix= cvCreateMat(NPoints,2,CV_32FC1); CvMat *project_image_matrix= cvCreateMat(NPoints,2,CV_32FC1); CvMat *rotation_matrix_1= cvCreateMat(1,3,CV_32FC1); CvMat *translation_matrix_1= cvCreateMat(1,3,CV_32FC1); CvMat *rotation_matrix= cvCreateMat(3,1,CV_32FC1); CvMat *translation_matrix= cvCreateMat(3,1,CV_32FC1); double err=0; cvGetRows(object_points,object_matrix,CurrentImage*NPoints,(CurrentImage+1)*NPoints,1); cvGetRow(rotation_vectors,rotation_matrix_1,CurrentImage); cvReshape(rotation_matrix_1,rotation_matrix,0,3); cvGetRow(translation_vectors,translation_matrix_1,CurrentImage); cvReshape(translation_matrix_1,translation_matrix,0,3); cvGetRows(image_points,project_image_matrix,CurrentImage*NPoints,(CurrentImage+1)*NPoints,1); cvProjectPoints2(object_matrix,rotation_matrix,translation_matrix, intrinsic_matrix,distortion_coeffs,image_matrix,0,0,0,0,0); err=cvNorm(image_matrix,project_image_matrix,CV_L2,0); printf("第%d幅图像的误差为%f/n",CurrentImage+1,err); fprintf(fp,"第%d幅图像的误差为%f/n",CurrentImage+1,err); } cvNamedWindow("Undistort_image",1); //显示校正后的图片 printf("/n"); printf("校正后的图片..../n"); for(CurrentImage=0;CurrentImage<NImages;CurrentImage++) { //加载图片 if((srcimage=cvLoadImage(argv[CurrentImage+1],1))!=0) { //色彩转换 cvCvtColor(srcimage,grayimage,CV_BGR2GRAY); cvUndistort2(grayimage,result_image,intrinsic_matrix,distortion_coeffs); cvShowImage("Undistort_image",result_image); printf("按任意键显示下一幅图片。。。/n"); cvWaitKey(0); } } //关闭文件 fclose(fp); //释放内存 cvWaitKey(0); free(corner_counter); free(temppoints); free(corners); cvDestroyWindow("Undistort_image"); cvDestroyWindow("Image"); cvReleaseMat(&intrinsic_matrix); cvReleaseMat(&distortion_coeffs); cvReleaseMat(&rotation_vectors); cvReleaseMat(&translation_vectors); cvReleaseMat(&rotation_matrix); cvReleaseMat(&translation_matrix); cvReleaseMat(&points_counts); cvReleaseMat(&object_points); cvReleaseMat(&image_points ); cvReleaseMat(&temp_matrix ); cvReleaseImage(&srcimage); cvReleaseImage(&result_image); cvReleaseImage(&grayimage); return -1;}/*********************************函数名: PrintMat(CvMat *matrix)函数输入:matrix指针 数据类型opencv规定的任意一个函数作用:在屏幕上打印矩阵**********************************/void PrintMat(CvMat *matrix,BOOL save_or_show,FILE *fp){ int i=0; int j=0; for(i=0;i < matrix->rows;i++)//行 { if (save_or_show) { fprintf(fp,"/n"); } else { printf("/n"); } switch(matrix->type&0X07) { case CV_32F: case CV_64F: { for(j=0;j<matrix->cols;j++)//列 { if (save_or_show) { fprintf(fp,"%9.3f ",(float)cvGetReal2D(matrix,i,j)); } else { printf("%9.3f ",(float)cvGetReal2D(matrix,i,j)); } } break; } case CV_8U: case CV_16U: { for(j=0;j<matrix->cols;j++) { printf("m ",(int)cvGetReal2D(matrix,i,j)); if (save_or_show) { fprintf(fp,"m ",(int)cvGetReal2D(matrix,i,j)); } else { printf("m ",(int)cvGetReal2D(matrix,i,j)); } } break; } default: break; } } }