• opencv单目摄像机标定(一)


      

     #include <string>  
        #include <iostream>  
        #include <cv.h>  
        #include <highgui.h>  
    
          
        using namespace std;  
          
        int main()  
        {  
            int cube_length=7;  
          
            CvCapture* capture;  
            capture=cvCreateCameraCapture(0); // opencv调用摄像头的接口,初始化从摄像头中获取视频,
          
            if(capture==0){  
                printf("无法捕获摄像头设备!
    
    ");  
                return 0;  
            }else{  
                printf("捕获摄像头设备成功!!
    
    ");  
            }   
            cvNamedWindow("摄像机帧截取窗口",1); //cvNamedWindow()函数用于在屏幕上创建一个窗口,将被显示的图像包含于该窗口中。函数的第一个参数指定了该窗口的窗口标题,如果要使用HighGUI库所提供的其他函数与该窗口进行交互时,我们将通过该参数值引用这个窗口。     
            printf("按“C”键截取当前帧并保存为标定图片...
    按“Q”键退出截取帧过程...
    
    ");  
    
            IplImage* frame; 
            int number_image=1;  //摄像机拍摄图像张数初始化
            char filename[20]="";  
            while(true)  
            {  
                frame=cvQueryFrame(capture);// 从摄像头或者文件中抓取并返回一帧   
                if(!frame)  
                     break;  
                cvShowImage("摄像机帧截取窗口",frame); //图像显示      
                if(cvWaitKey(10)=='c')
                 {  
                    sprintf (filename,"%d.jpg",number_image);  // int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ... ); //这个函数的主要作用是将若干个argument按照format格式存到buffer中    
                    cvSaveImage(filename,frame);  //保存,在工作目录中 
                    cout<<"成功获取当前帧,并以文件名"<<filename<<"保存...
    
    ";  
                    printf("按“C”键截取当前帧并保存为标定图片...
    按“Q”键退出截取帧过程...
    
    ");  
                    number_image++;  
                 }
                 else if(cvWaitKey(10)=='q')
                {  
                    printf("截取图像帧过程完成...
    
    ");  
                    cout<<"共成功截取"<<--number_image<<"帧图像!!
    
    ";  
                    break;  
                }  
            }  
          
            cvReleaseImage(&frame);  //释放图像  
            cvReleaseCapture(&capture);//若您的是1.0版本,如果报错请修改为cvReleaseCapture(&capture),或将此句加在cvReleaseImage(&frame)后
            cvDestroyWindow("摄像机帧截取窗口");  
          
            IplImage * show; //RePlay图像指针
            cvNamedWindow("RePlay",1);  
            int a=1;  //临时变量,表示在操作第a帧图像
            int number_image_copy=number_image; //复制图像帧数 
            CvSize board_size=cvSize(7,7);   // Cvsize:OpenCV的基本数据类型之一,是构造Cvsize类型的函数,width和height,表示矩阵框大小,以像素为精度。与CvPoint结构类似,但数据成员是integer类型的width和height。    
            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* cvCreateMat( int rows, int cols, int type );rows矩阵行数。cols矩阵列数。type矩阵元素类型,浮点型的单通道图像。
    // 这里type可以是任何预定义类型,预定义类型的结构如下:CV_<bit_depth> (S|U|F)C<number_of_channels>。      
            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;  //存储步长,step=successes*total_per_image; 
            int successes=0; //成功找到标定板上所有角点的图像帧数初始化
          
            while(a<=number_image_copy)
           {  //读取每张图
                sprintf (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<<"帧图片无法找到棋盘格所有角点!
    
    ";  
                    cvNamedWindow("RePlay",1);  
                    cvShowImage("RePlay",show);  
                    cvWaitKey(0);  
                   }
               else{  
                    cout<<""<<a<<"帧图像成功获得"<<count<<"个角点...
    ";  
                    cvNamedWindow("RePlay",1);  
          
                    IplImage * gray_image= cvCreateImage(cvGetSize(show),8,1); //创建头并分配数据IplImage* 
                    cvCvtColor(show,gray_image,CV_BGR2GRAY); // cvCvtColor(...),是Opencv里的颜色空间转换函数,可以实现rgb颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。     
                    cout<<"获取源图像灰度图过程完成...
    ";  
                 //获取亚像素角点
                    cvFindCornerSubPix(gray_image,image_points_buf,count,cvSize(11,11),cvSize(-1,-1),  
                                        cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1));  
                    cout<<"灰度图亚像素化过程完成...
    ";  
                  //绘制角点 
                    cvDrawChessboardCorners(show,board_size,image_points_buf,count,found);
                    cout<<"在源图像上绘制角点过程完成...
    
    ";  
                    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)
                   {
     //total_per_image是一幅图像中的角点总数。  
     // opencv中用来访问矩阵每个元素的宏,这个宏只对单通道矩阵有效,CV_MAT_ELEM( matrix, elemtype, row, col )参数  matrix:要访问的矩阵  elemtype:矩阵元素的类型  row:所要访问元素的行数  col:所要访问元素的列数   
    // cvFindCornerSubPix求完每个角点横纵坐标值都存在image_point_buf里,现在将其存在image_points中,每行存一个,商为行x,余为列y    
    //将角点坐标的数组压入矩阵image_points
                        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; //0单精度浮点 
                    }  
                    CV_MAT_ELEM(*point_counts,int,successes,0)=total_per_image;//访问矩阵角点数  
                    successes++; 
                }  
                a++;  
            }  
          
            cvReleaseImage(&show);  
            cvDestroyWindow("RePlay");  
          
            cout<<"*********************************************
    ";  
            cout<<number_image<<"帧图片中,标定成功的图片为"<<successes<<"帧...
    ";  
            cout<<number_image<<"帧图片中,标定失败的图片为"<<number_image-successes<<"帧...
    
    ";  
            cout<<"*********************************************
    
    ";  
          
            cout<<"按任意键开始计算摄像机内参数...
    
    ";  
          
            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;//fx  
            CV_MAT_ELEM(*intrinsic_matrix,float,1,1)=1.0f;//fy 
    
           //标定相机的内参矩阵和畸变系数向量
           cvCalibrateCamera2(object_points2,image_points2,point_counts2,cvGetSize(show_colie),  
                                intrinsic_matrix,distortion_coeffs,NULL,NULL,0);  
              
            cout<<"摄像机内参数矩阵为:
    ";  
            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)  
                                                          <<"
    
    ";  
            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)  
                                                          <<"
    
    ";  
            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)  
                                                          <<"
    
    ";  
          
            cout<<"畸变系数矩阵为:
    ";  
            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)  
                                                           <<"
    
    ";  
          
            cvSave("Intrinsics.xml",intrinsic_matrix);//保存在工作目录下   
            cvSave("Distortion.xml",distortion_coeffs);  
          
            cout<<"摄像机矩阵、畸变系数向量已经分别存储在名为Intrinsics.xml、Distortion.xml文档中
    
    ";  
          
            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);//函数cvInitUndistortMap预先计算非形变对应-正确图像的每个像素在形变图像里的坐标。这个对应可以传递给cvRemap函数(跟输入和输出图像一起)。   
           
            cvNamedWindow("原始图像",1);  
            cvNamedWindow("非畸变图像",1);  
          
            cout<<"按‘E’键退出显示...
    
    ";  
          
            while(show_colie){  
                IplImage * clone=cvCloneImage(show_colie);  
                cvShowImage("原始图像",show_colie);  
                cvRemap(clone,show_colie,mapx,mapy);//校正图像,输入为clone,结果为show_colie    
                cvReleaseImage(&clone);  
                cvShowImage("非畸变图像",show_colie);  
          
                if(cvWaitKey(10)=='e'){  
                    break;  
                }  
          
                show_colie=cvQueryFrame(capture1);  
            }  
          
            return 0;  
              
        }  

     

  • 相关阅读:
    Asp.net技术点GridView+AspnetPager+Linq+ViewState 处理数据条件问题
    向本地添加jar包的经历
    elasticsearch 相关(ELK)
    elastaicsearch简单入门项目
    Zlibrary链接,全球最大的数字图书馆Zlibrary
    以短链服务为例,探讨免AppKey、免认证、Ajax跨域调用新浪微博API
    在线伪原创工具www.bolewei.com的开发过程
    如何用three.js(webgl)搭建3D粮仓、3D仓库、3D物联网设备监控第十二课
    如何用webgl(three.js)搭建处理3D隧道、3D桥梁、3D物联网设备、3D高速公路、三维隧道桥梁设备监控第十一课
    Windows、Ubuntu双系统 + 固态硬盘、机械硬盘通过Grub引导
  • 原文地址:https://www.cnblogs.com/Jessica-jie/p/6118827.html
Copyright © 2020-2023  润新知