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;
}

  

时间: 2024-10-13 09:36:13

Opencv摄像头标定(参数+校正),但cvFindChessboardCorners不太稳定,必须标版的相关文章

基于OpenCV立体视觉标定和校正

这几天学习双目视觉标定,分别使用了两种工具:OpenCV和Matlab.Matlab的效果非常稳定,但是一开始OpenCV的效果很糟糕,要不是出现中断就是标定出来的结果数值很大.经过了几天的不断调试和更改,终于把OpenCV的立体视觉标定和校正的程序写出来了.立体标定时计算空间上的两台摄像机几何关系的过程,立体校正则是对个体图像进行纠正,保证这些图像可以从平面对准的两幅图像获得.程序的框架如下: 1.读取左右相机图片序列 双目相机的图片序列放在Demon的路径下,左右相机的图像的名字分别存放在两

OpenCV使用标定图

本文由 @lonelyrains 出品,转载请注明出处. 文章链接: http://blog.csdn.net/lonelyrains/article/details/46915705 上一步生成标定图參考上一篇文章OpenCV生成标定图. 在生成标定图之后,须要用A4纸打印下来.才干拿到摄像头以下摆弄. 笔者使用的是imagelist图片列表的方式使用标定图.即先用摄像头拍一部分图片,然后再由以下说的校准project校准得到畸变參数--主要原因是还没有搞清楚怎么实时获取这个摄像头(海康威视)

opencv 摄像头

VideoCapture cap(0); if(!cap.isOpened()) return -1; Mat frame, edges; namedWindow("edges",1); for(;;) { cap >> frame; cvtColor(frame, edges, CV_BGR2GRAY); GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5); Canny(edges, edges, 0, 30, 3); imsh

摄像头标定

今天在调试摄像头标定的时候发现了几个问题: fs.open("result.xml", FileStorage::WRITE); fs<<"cameraMatrix"<<cameraMatrix; fs<<"distortCoeffs"<<distCoeffs; fs.release(); 字符串中间不能空格 初始化必须加(1) vector< vector<Point3f> &g

OpenCV相机标定

相机标定 相机标定:简单的说,就是获得相机参数的过程.参数如:相机内参数矩阵,投影矩阵,旋转矩阵和平移矩阵等 什么叫相机参数? 简单的说,将现实世界中的人.物,拍成一张图像(二维).人或物在世界中的三维坐标,和图像上对应的二维坐标间的关系.表达两种不同维度坐标间的关系用啥表示?用相机参数. 相机的成像原理 先来看一下,相机的成像原理: 如图所示,这是一个相机模型.将物体简化看成一个点.来自物体的光,通过镜头,击中图像平面(图像传感器),以此成像.d0是物体到镜头的距离,di时镜头到图像平面的距离

Matlab 摄像机标定+畸变校正

博客转载自:http://blog.csdn.net/Loser__Wang/article/details/51811347 本文目的在于记录如何使用MATLAB做摄像机标定,并通过opencv进行校正后的显示. 首先关于校正的基本知识通过OpenCV官网的介绍即可简单了解: http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html 对于摄像机我们所关心的主要参数为摄像

OpenCV摄像头人脸识别

注: 从外设摄像装置中获取图像帧,把每帧的图片与人脸特征进行匹配,用方框框住识别出来的人脸 需要用到的函数: CvHaarClassifierCascade* cvLoadHaarClassifierCascade( const char* directory, CvSize orig_window_size ); 第一个参数:训练好的级联分类器的路径 第二个参数:级联分类器训练中采用的检测目标的尺寸 #include "stdafx.h" #include "iostrea

OpenCV相机标定及距离估计(单目)

相机标定基本知识 对于摄像机模型,一幅视图是通过透视变换将三维空间中的点投影到图像平面.投影公式如下: 或者 这里(X, Y, Z)是一个点的世界坐标,(u, v)是点投影在图像平面的坐标,以像素为单位.A被称作摄像机矩阵,或者内参数矩阵.(cx, cy)是基准点(通常在图像的中心),fx, fy是以像素为单位的焦距.所以如果因为某些因素对来自于摄像机的一幅图像升采样或者降采样,所有这些参数(fx, fy, cx和cy)都将被缩放(乘或者除)同样的尺度.内参数矩阵不依赖场景的视图,一旦计算出,可

opencv相机标定(Python)

相机标定 相机标定的目的 获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像. 相机标定的输入 标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上). 相机标定的输出 摄像机的内参.外参系数. 拍摄的物体都处于三维世界坐标系中,而相机拍摄时镜头看到的是三维相机坐标系,成像时三维相机坐标系向二维图像坐标系转换.不同的镜头成像时的转换矩阵不同,同时可能