opencv单目相机标定例程

嵌入式设计应用

130人已加入

描述

  OpenCV sample目录下自带两个与相机标定的cpp文件即:calibration.cpp和calibration_artificial.cpp

  calibration.cpp 是通过用户输入可选参数进行摄像机标定的程序。

  calibration_artificial.cpp 是程序模拟模拟摄像机标定的过程,即程序创建棋盘然后自主标定。

  通常我们有两种方式去标定,一个是实时的从摄像机获取拍摄到的棋盘进行标定,一个是已经获得了一些棋盘的图片来标定。

  本文详细介绍第二种,即用已获得的棋盘图片的整个过程。

  方法一:编译生成 .exe文件,然后在commond 窗口输入参数执行

  方法二:通过添加输入参数的代码,然后执行(可以单步调试)(推荐此方法)

  calibration.cpp 和 calibration_artificial.cpp 位置如图所示。此外,棋盘图片也在同一目录下

  OpenCV

  OpenCV

  找到文件后,开始新建工程吧。不过在用以获得的图像来进行标定,应先通过OpenCV自带的imagelist_creator.cpp 产生一个xml或者yaml格式的图像列表,然后在使用下面的程序。

  第一步,新建项目demo,添加刚才那个目录下的imagelist_creator.cpp 编译执行得到可执行文件 demo.exe

  OpenCV

  第二步,执行demo.exe 产生一个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

  OpenCV

  第三步,进行相机的标定

  先把14张棋盘图片放到debug目录下,然后移除imagelist_creator.cpp 添加 calibration.cpp ,如图所示

  OpenCV

  编译执行,得到新的demo.exe ,进入cmd ,输入 demo -w 6 -h 9 imagelist.yaml 回车即可。如图所示,开始对每张图片进行角点检测

  OpenCV

  最后,得到一个 out_camera_data.yml 文件

  OpenCV

  内容如下:

  %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

  此时,大功告成 =。=

  //对于想自己单步调试的亲,补充第二种方法,即通过添加代码调试。

  第一步:将图片及imagelist放到 D:\Workspace\demo\demo目录下

  第二步: 添加代码

  具体过程如图所示:

  OpenCV

  在该目录下放入imagelist.yaml 和14张图片

  OpenCV

  添加代码

  argc = 6;

  argv[0] = “demo.exe”;

  argv[1] = “-w”;

  argv[2] = “6”;

  argv[3] = “-h”;

  argv[4] = “9”;

  argv[5] = “imagelist.yaml”;

  OpenCV

  代码

  #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(“无法捕获摄像头设备!\n\n”);

  return 0;

  }else{

  printf(“捕获摄像头设备成功!!\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\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”;

  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《《“畸变系数矩阵为:\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《《“摄像机矩阵、畸变系数向量已经分别存储在名为Intrinsics.xml、Distortion.xml文档中\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;

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分