照例,在正式贴代码之前要说一段废话。这个是我毕业论文做的东西,之前也是在这个算法中做了很多测试,后来发现要用的时候,系统重装而且没有备份。所以这次写了一个极简的标定程序,用于临时的项目测试。
至于自定义头文件“CommonHead.h”就只是一个void std_calibration(char**);的申明,就不贴代码了。
/*
利用OpenCV完成相机的标定
@author cyoubo
@DateTime 2015.9.8
@OpenCV Version 2.4.10
*/
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CommonHead.h"
void std_calibration(char** path)
{
//分别表示棋盘格的行数、列数、张数、共计角点数、有效棋盘影像张数、当前处理影像编号
int b_w=6,b_h=9,n_b=5,b_n,success=0,step=0;
//计算共计棋盘角点数
b_n=b_w*b_h;
//创建棋盘规格Size
CvSize board_sz=CvSize();
board_sz.width=b_w;
board_sz.height=b_h;
//创建搜索窗Size
CvSize winSize=CvSize();
winSize.width=11;
winSize.height=11;
//创建拒绝域Size
CvSize noSize=CvSize();
noSize.width=-1;
noSize.height=-1;
//创建影像尺寸Size,具体值等待后期输入
CvSize imageSize=CvSize();
//创建迭代需求对象
CvTermCriteria term;
term.type=CV_TERMCRIT_EPS+CV_TERMCRIT_ITER;
term.epsilon=0.1;
term.max_iter=30;
CvMat* image_point=cvCreateMat(n_b*b_n,2,CV_32FC1);
CvMat* object_point=cvCreateMat(n_b*b_n,3,CV_32FC1);
CvMat* point_count=cvCreateMat(n_b,1,CV_32SC1);
CvMat* Intrinsic=cvCreateMat(3,3,CV_32FC1);
CvMat* Distortion=cvCreateMat(5,1,CV_32FC1);
//循环获取影像中的角点
for(int index=0;index<n_b;index++)
{
int conner_count;
CvPoint2D32f* corners=new CvPoint2D32f[b_n];
IplImage *image =cvLoadImage(path[index]);
imageSize=cvGetSize(image);
IplImage *gray_image=cvCreateImage(imageSize,8,1);
cvCvtColor(image,gray_image,CV_BGR2GRAY);
int found=cvFindChessboardCorners(gray_image,board_sz,corners,&conner_count,CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
if(conner_count==b_n)
{
cvFindCornerSubPix(gray_image,corners,conner_count,winSize,noSize,term);
if(b_n==conner_count)
{
step=success*b_n;
for (int i = step, j = 0; j < b_n; ++i, ++j)
{
CV_MAT_ELEM(*image_point, float, i, 0) = corners[j].x;
CV_MAT_ELEM(*image_point, float, i, 1) = corners[j].y;
CV_MAT_ELEM(*object_point, float, i, 0) = (j/b_w);
CV_MAT_ELEM(*object_point, float, i, 1) = (j % b_w);
CV_MAT_ELEM(*object_point, float, i, 2) = 0.0f;
}
CV_MAT_ELEM(*point_count, int, success, 0) = b_n;
success++; //如果个数一致,则认为改张影像有效
}
}
}
//依据有效影像重新创建标定解算的像控点对
CvMat* image_point2 = cvCreateMat(b_n*(success), 2, CV_32FC1);
CvMat* object_point2 = cvCreateMat(b_n*(success), 3, CV_32FC1);
CvMat* point_count2 = cvCreateMat((success), 1, CV_32SC1);
for (int i = 0; i < success*b_n; ++i)
{
CV_MAT_ELEM(*image_point2, float, i, 0) = CV_MAT_ELEM(*image_point, float, i, 0);
CV_MAT_ELEM(*image_point2, float, i, 1) = CV_MAT_ELEM(*image_point, float, i, 1);
CV_MAT_ELEM(*object_point2, float, i, 0) = CV_MAT_ELEM(*object_point, float, i, 0);
CV_MAT_ELEM(*object_point2, float, i, 1) = CV_MAT_ELEM(*object_point, float, i, 1);
CV_MAT_ELEM(*object_point2, float, i, 2) = CV_MAT_ELEM(*object_point, float, i, 2);
}
for (int i = 0; i < success; ++i)
{
CV_MAT_ELEM(*point_count2, int, i, 0) = CV_MAT_ELEM(*point_count, int, i, 0);
}
cvReleaseMat(&object_point);
cvReleaseMat(&image_point);
cvReleaseMat(&point_count);
//设置内方位元素中主距分量的初始值为1,并开始迭代解算
CV_MAT_ELEM(*Intrinsic, float, 0, 0) = 1.0f;
CV_MAT_ELEM(*Intrinsic, float, 1, 1) = 1.0f;
double Rmse=cvCalibrateCamera2
(
object_point2,
image_point2,
point_count2,
board_sz,
Intrinsic,
Distortion,
NULL,
NULL,
0
);
printf("the rms is %f",Rmse);
cvSave("G:\\Intrinsic.xml", Intrinsic);
cvSave("G:\\Distortion.xml", Distortion);
cvReleaseMat(&image_point2);
cvReleaseMat(&object_point2);
cvReleaseMat(&point_count2);
//依据标定结果重绘影像
IplImage *mapx=cvCreateImage(imageSize,IPL_DEPTH_32F,1);
IplImage *mapy=cvCreateImage(imageSize,IPL_DEPTH_32F,1);
cvInitUndistortMap(Intrinsic,Distortion,mapx,mapy);
IplImage *src_map=cvLoadImage(path[1]);
IplImage *dst_map=cvCloneImage(src_map);
cvRemap(src_map,dst_map,mapx,mapy);
cvSaveImage("G:\\result2.jpeg",dst_map);
cvReleaseImage(&src_map);
cvReleaseImage(&dst_map);
cvReleaseImage(&mapx);
cvReleaseImage(&mapy);
}