OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 103373|回复: 171

【代码】单目摄像机标定程序_分享

[复制链接]
发表于 2012-3-27 16:51:35 | 显示全部楼层 |阅读模式
关于双目立体视觉的源代码我放在了本帖第四页上,感兴趣的朋友可以查阅

该程序的修改版本我发在这个帖子的第二页上了,比以下程序性能更好,开始想直接覆盖了,但是这两个版本设置世界坐标系的坐标方式不同,感兴趣的朋友可以看一下,所以我也就没删

如果转载,请注明出处http://blog.csdn.net/guvcolie/article/details/7454632

我自己写了一个摄像机标定程序,核心算法参照learning  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(&quot;无法捕获摄像头设备!\n\n&quot;);
                return 0;
        }else{
                printf(&quot;捕获摄像头设备成功!!\n\n&quot;);
        }

        IplImage* frame;

        cvNamedWindow(&quot;摄像机帧截取窗口&quot;,1);

        printf(&quot;按“C”键截取当前帧并保存为标定图片...\n按“Q”键退出截取帧过程...\n\n&quot;);

        int number_image=1;
        char *str1;
        str1=&quot;.jpg&quot;;
        char filename[20]=&quot;&quot;;

        while(true)
        {
                frame=cvQueryFrame(capture);
                if(!frame)
                         break;
                cvShowImage(&quot;摄像机帧截取窗口&quot;,frame);
               
                if(cvWaitKey(10)=='c'){
                        sprintf_s (filename,&quot;%d.jpg&quot;,number_image);
                        cvSaveImage(filename,frame);
                        cout<<&quot;成功获取当前帧,并以文件名&quot;<<filename<<&quot;保存...\n\n&quot;;
                        printf(&quot;按“C”键截取当前帧并保存为标定图片...\n按“Q”键退出截取帧过程...\n\n&quot;);
                        number_image++;
                }else if(cvWaitKey(10)=='q'){
                        printf(&quot;截取图像帧过程完成...\n\n&quot;);
                        cout<<&quot;共成功截取&quot;<<--number_image<<&quot;帧图像!!\n\n&quot;;
                        break;
                }
        }

        cvReleaseImage(&frame);//若您的是1.0版本,如果报错请修改为cvReleaseCapture(&capture),或将此句加在cvReleaseImage(&frame);后
        cvDestroyWindow(&quot;摄像机帧截取窗口&quot;);

        IplImage * show;
        cvNamedWindow(&quot;RePlay&quot;,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,&quot;%d.jpg&quot;,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<<&quot;第&quot;<<a<<&quot;帧图片无法找到棋盘格所有角点!\n\n&quot;;
                        cvNamedWindow(&quot;RePlay&quot;,1);
                        cvShowImage(&quot;RePlay&quot;,show);
                        cvWaitKey(0);

                }else{
                        cout<<&quot;第&quot;<<a<<&quot;帧图像成功获得&quot;<<count<<&quot;个角点...\n&quot;;
               
                        cvNamedWindow(&quot;RePlay&quot;,1);

                        IplImage * gray_image= cvCreateImage(cvGetSize(show),8,1);
                        cvCvtColor(show,gray_image,CV_BGR2GRAY);
                        cout<<&quot;获取源图像灰度图过程完成...\n&quot;;
                        cvFindCornerSubPix(gray_image,image_points_buf,count,cvSize(11,11),cvSize(-1,-1),
                                                                cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,30,0.1));
                        cout<<&quot;灰度图亚像素化过程完成...\n&quot;;
                        cvDrawChessboardCorners(show,board_size,image_points_buf,count,found);
                        cout<<&quot;在源图像上绘制角点过程完成...\n\n&quot;;
                        cvShowImage(&quot;RePlay&quot;,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(&quot;RePlay&quot;);


        cout<<&quot;*********************************************\n&quot;;
        cout<<number_image<<&quot;帧图片中,标定成功的图片为&quot;<<successes<<&quot;帧...\n&quot;;
        cout<<number_image<<&quot;帧图片中,标定失败的图片为&quot;<<number_image-successes<<&quot;帧...\n\n&quot;;
        cout<<&quot;*********************************************\n\n&quot;;

        cout<<&quot;按任意键开始计算摄像机内参数...\n\n&quot;;


        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<<&quot;摄像机内参数矩阵为:\n&quot;;
        cout<<CV_MAT_ELEM(*intrinsic_matrix,float,0,0)<<&quot;    &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,0,1)
                                                                                                                        <<&quot;    &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,0,2)
                                                                                                                        <<&quot;\n\n&quot;;
        cout<<CV_MAT_ELEM(*intrinsic_matrix,float,1,0)<<&quot;    &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,1,1)
                                                                                                                        <<&quot;    &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,1,2)
                                                                                                                        <<&quot;\n\n&quot;;
        cout<<CV_MAT_ELEM(*intrinsic_matrix,float,2,0)<<&quot;    &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,2,1)
                                                                                                                        <<&quot;          &quot;<<CV_MAT_ELEM(*intrinsic_matrix,float,2,2)
                                                                                                                        <<&quot;\n\n&quot;;

        cout<<&quot;畸变系数矩阵为:\n&quot;;
        cout<<CV_MAT_ELEM(*distortion_coeffs,float,0,0)<<&quot;    &quot;<<CV_MAT_ELEM(*distortion_coeffs,float,1,0)
                                                                                                                        <<&quot;    &quot;<<CV_MAT_ELEM(*distortion_coeffs,float,2,0)
                                                                                                                        <<&quot;    &quot;<<CV_MAT_ELEM(*distortion_coeffs,float,3,0)
                                                                                                                        <<&quot;    &quot;<<CV_MAT_ELEM(*distortion_coeffs,float,4,0)
                                                                                                                        <<&quot;\n\n&quot;;

        cvSave(&quot;Intrinsics.xml&quot;,intrinsic_matrix);
        cvSave(&quot;Distortion.xml&quot;,distortion_coeffs);

        cout<<&quot;摄像机矩阵、畸变系数向量已经分别存储在名为Intrinsics.xml、Distortion.xml文档中\n\n&quot;;

        CvMat * intrinsic=(CvMat *)cvLoad(&quot;Intrinsics.xml&quot;);
        CvMat * distortion=(CvMat *)cvLoad(&quot;Distortion.xml&quot;);

        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(&quot;原始图像&quot;,1);
        cvNamedWindow(&quot;非畸变图像&quot;,1);

        cout<<&quot;按‘E’键退出显示...\n\n&quot;;

        while(show_colie){
                IplImage * clone=cvCloneImage(show_colie);
                cvShowImage(&quot;原始图像&quot;,show_colie);
                cvRemap(clone,show_colie,mapx,mapy);
                cvReleaseImage(&clone);
                cvShowImage(&quot;非畸变图像&quot;,show_colie);

                if(cvWaitKey(10)=='e'){
                        break;
                }

                show_colie=cvQueryFrame(capture1);
        }

        return 0;
       
}
回复

使用道具 举报

 楼主| 发表于 2012-5-1 10:41:40 | 显示全部楼层

【代码】单目摄像机标定程序_分享

“这个点”就是标定板上面的一个角点,顺便问一下,1、摄像机标定需要输入方格的尺寸吗?我的小方格是21.6mm。
“这个点”是一个三维点!在标定的时候我们默认Z轴为0.    你可以看一下这个帖子http://www.opencv.org.cn/forum/viewtopic.php?f=10&t=11802&p=44559&hilit=%E5%8F%8C%E7%9B%AE#p44559
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2012-5-6 13:17:16 | 显示全部楼层

【代码】单目摄像机标定程序_分享

在MFC程序中,自定义了一个类,在该类中的成员函数里无法使用CV_MAT_ELEM这个宏对矩阵初始化,怎么办?
抱歉  我没学过MFC   你可以到技术群咨询下
回复 支持 0 反对 1

使用道具 举报

 楼主| 发表于 2012-4-22 12:13:36 | 显示全部楼层

【代码】单目摄像机标定程序_分享

好东西大家share~谢谢lz~
谢谢啊 这是我的博客  <!-- m --><a class=\"postlink\" href=\"http://blog.csdn.net/guvcolie/article/details/7453680\">http://blog.csdn.net/guvcolie/article/details/7453680</a><!-- m --> 刚刚开始建  原创会陆续贴上去  希望对大家有帮助!
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2012-3-30 13:56:00 | 显示全部楼层

【代码】单目摄像机标定程序_分享

这个代码可以以此继续写立体标定的代码!
有做这一部分的朋友可以接续写下去,多多分享!
回复 支持 反对

使用道具 举报

发表于 2012-4-1 11:58:03 | 显示全部楼层

【代码】单目摄像机标定程序_分享

谢谢楼主分享,我也研究研究,看能不能写出个立体标定程序出来。
回复 支持 反对

使用道具 举报

发表于 2012-4-10 14:18:23 | 显示全部楼层

【代码】单目摄像机标定程序_分享

立体标定是什么意思
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-4-11 17:53:57 | 显示全部楼层

【代码】单目摄像机标定程序_分享

立体标定是什么意思
就是双目摄像机标定   主要计算两个镜头之间的R和t矩阵
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-4-11 17:54:58 | 显示全部楼层

【代码】单目摄像机标定程序_分享

谢谢楼主分享,我也研究研究,看能不能写出个立体标定程序出来。
好   要是写出来多多跟帖分享哈
回复 支持 反对

使用道具 举报

发表于 2012-4-18 12:36:00 | 显示全部楼层

【代码】单目摄像机标定程序_分享

用上边的程序标定后图像反正畸变了,求原因啊
回复 支持 反对

使用道具 举报

发表于 2012-4-19 21:47:12 | 显示全部楼层

【代码】单目摄像机标定程序_分享

好东西大家share~谢谢lz~
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-4-22 12:10:21 | 显示全部楼层

【代码】单目摄像机标定程序_分享

用上边的程序标定后图像反正畸变了,求原因啊
你用的摄像机是什么摄像机?   如果是那种低端的插电脑上得摄像头就会出现这种情况   因为你在获取棋盘角点的过程就已经出现误差了   你不妨看看每张标定的图片圈出的角点的位置是否大致在一条线上?   
我的核心算法就是和书上的一样   只是过程修改下   你试试    共同探讨下
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-3-29 17:13 , Processed in 0.014715 second(s), 17 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表