




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
基于机器视觉的摄像机标定方法研究0引言机器视觉的基本任务之一是从摄像机获取图像信息并计算三维空间中物体的几何信息,以由此重建和识别物体。而空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系是由摄像机成像的几何模型决定的,这些几何模型参数就是摄像机参数。在大多数条件下,这些参数必须通过实验与计算才能得到,这个过程被称为摄像机定标(或称为标定)。标定过程就是确定摄像机的几何和光学参数,以及摄像机相对于世界坐标系的方位。由于标定精度的大小,直接影响着计算机视觉(机器视觉)的精度。因此,只有做好了摄像机标定工作,后续工作才能正常展开,可以说,提高标定精度也是当前科研工作的重要方面。摄像机透视投影模型摄像机通过成像透镜将三维场景投影到摄像机二维像平面上,这个投影可用成像变换(即摄像机成像模型)来描述。摄像机成像模型分为线形模型和非线性模型。针孔成像模型就属于线形摄像机模型,本文就讨论在这种模型下,某空间点与其图像投影点在各种坐标系下的变换关系。图1所示为三个不同层次的坐标系在针孔成像模型下的关系。其中(Xw,Yw,Zw)为世界坐标系,(x,y,z)为摄像机坐标系,XfQfYf为以像素为单位的图像坐标系,XOY为以毫米为单位的图像坐标系。YL21标定就抚的坐标星Pu<Kia,Yj}YL21标定就抚的坐标星Pu<Kia,Yj}P瞅山如)图像中某点在以毫米为单位的图像坐标系中的坐标与其在以像素为单位的图像坐标系中的坐标的变换关系如下:空间某点在世界坐标系中的坐标与其在摄像机坐标系中的坐标变换关系如下:其中,为3X3正父单位矩;t为三维平移向量;M2为4X4矩阵。由于针孔成像模型有如下关系:所以,将(1),(2)代入上式的齐次坐标和矩阵表示可得:i码°呦0w1i码°呦0w10.01.1.0010其中,Ml为摄像机内参数,M2为摄像机外参数。确定某一摄像机参数称为摄像机定标。标定分类总的来说,摄像机标定可以分为传统的摄像机标定方法和摄像机自标定方法两大类。传统摄像机标定的基本方法是在一定的摄像机模型下,通过对特定标定参照物进行图像处理,并利用一系列数学变换公式计算及优化,来求取摄像机模型内部参数和外部参数。然而,该方法在场景未知和摄像机任意运动的一般情况下,其标定很难实现。20世纪90年代初,Faugeras,Luong,Maybank等人首次提出了摄像机自标定方法。这种自标定法利用摄像机本身参数之间的约束关系来标定,而与场景和摄像机的运动无关,所以更为灵活。传统摄像机标定方法传统的摄像机标定方法按照标定参照物与算法思路可以分成若干类,如基于3D立体靶标的摄像机标定、基于2D平面靶标的摄像机标定、以及基于径向约束的摄像机标定等。3.1基于3D立体靶标的摄像机标定基于3D立体靶标进行摄像机标定是将一个3D立体靶标放置在摄像机前,靶标上每一个小方块的顶点均可作为特征点。每个特征点相对于世界坐标系的位置在制作时应精确测定。摄像机获得靶标上特征点的图像后,由于表现三维空间坐标系与二维图像坐标系关系的方程是摄像机内部参数和外部参数的非线性方程,如果忽略摄像机镜头的非线性畸变并把透视变换矩阵中的元素作为未知数,来给定一组三维控制点和对应的图像点,那么,就可以利用直接线性变换法来求解透视变换矩阵中的各个元素。所以,由靶标上特征点的世界坐标和图像坐标,即可计算出摄像机的内外参数。3.2基于2D平面靶标的摄像机标定该方法又称为张正友标定法,这是一种适合应用的新型灵活方法。该方法要求摄像机在两个以上不同的方位拍摄一个平面靶标,摄像机和2D平面靶标都可以自由移动,且内部参数始终不变,假定2D平面靶标在世界坐标系中的Z=0,那么,通过线性模型分析就可计算出摄像机参数的优化解,然后用基干最大似然法进行非线性求精。在这个过程中得出考虑镜头畸变的目标函数后就可以求出所需的摄像机内、外部参数。这种标定方法既具有较好的鲁棒性,又不需昂贵的精制标定块,很有实用性。但是,张正友方法在进行线性内外参数估计时,由于假定模板图像上的直线经透视投影后仍然为直线,进而进行图像处理,这样,实际上会引入误差,所以,嘎方法在广角镜畸变比较大的情况误差较大。基于径向约束的摄像机标定Tsai(1986)给出了一种基于径向约束的两步法标定方法,该方法的核心是先利用RAC(径向一致约束)条件用最小二乘法解超定线性方程,以求出除tT(摄像机光轴方向的平移)外的其他像机外参数,然后再在摄像机有和无透镜畸变等两种情况下求解摄像机的其他参数。Tsai方法的精度比较高,适用于精密测量,但它对设备的要求也很高,不适用于简单的标定。这种方法的精度是以设备的精度和复杂度为代价的。摄像机自标定方法不依赖于标定参照物,仅利用摄像机在运动过程中周围环境图像与图像之间的对应关系来对摄像机进行的标定的方法称为摄像机自标定方法。目前已有的自标定技术大致可以分为基于主动视觉的摄像机自标定技术、直接求解Kruppa方程的摄像机自标定方法、分层逐步标定法、基于二次曲面的自标定方法等几种。基于主动视觉的自标定法所谓主动视觉系统,是指摄像机被固定在一个可以精确控制的平台上,且平台的参数可以从计算机精确读出,只需控制摄像机作特殊的运动来获得多幅图像然后利用图像和已知的摄像机运动参数来确定摄像机的内外参数。其代表性的方法是马颂德提出的基于两组三正交运动的线性方法,后来杨长江,李华等人提出了改进的方案,即分别是基于4组平面正交以及5组平面正交运动并利用图像中的极点信息来线性标定摄像机参数。此种自标定方法算法简单,可以获得线性解,不足之处在于必须有可以精确控制的摄像机运动平台。基于Kruppa方程的自标定方法Faugeras,Luong,Maybank等提出的自标定方法是直接基于求解Kruppa方程的一种方法,该方法利用绝对二次曲线像和极线变换的概念推导出Kruppa方程。基于Kxuppa方程的自标定方法不需要对图像序列做射影重建,而是对两图像之间建立方程,这个方法在某些很难将所有图像统一到一致的射影框架场合会比分层逐步标定法更具优势,但代价是无法保证无穷远平面在所有图像对确定的射影空间里的一致性,当图像序列较长时,基于Kruppa方程的自标定方法可能不稳定。且其鲁棒性依赖于给定的初值。分层逐步标定法近年来,分层逐步标定法已成为自标定研究中的热点,并在实际应用中逐渐取代了直接求解Kruppa方程的方法。分层逐步标定法首先要求对图像序列做射影重建,再通过绝对二次曲线(面)施加约束,最后定出仿射参数(即无穷远平面方程)和摄像机内参数。分层逐步标定法的特点是在射影标定的基础上,以某一幅图像为基准做射影对齐,从而将未知数数量缩减,再通过非线性优化算法同时解出所有未知数。不足之处在于非线性优化算法的初值只能通过预估得到,而不能保证其收敛性。由于射影重建时,都是以某参考图像为基准,所以,参考图像的选取不同,标定的结果也不同相。基于二次曲面的自标定方法Triggs是最早将绝对二次曲面的概念引入自标定的研究中来的,这种自标定方法与基于Kruppa方程的方法在本质上是相同的,它们都利用绝对二次曲线在欧氏变换下的不变性。但在输入多幅图像并能得到一致射影重建的情况下,基于二次曲面的自标定方法会更好一些,其根源在于二次曲面包含了无穷远平面和绝对二次曲线的所有信息,且基于二次曲面的自标定方法又是在对所有图像做射影重建的基础上计算二次曲面的,因此,该方法保证了无穷远平面对所有图像的一致性。结束语本文对基于机器视觉的摄像机标定理论与各种方法进行了研究。传统的摄像机标定需要标定参照物。为了提高计算精度,还需确定非线性畸变校正参数。而新的比较符合摄像机成像物理模型且又便于分析计算的实用模型是条另辟蹊径的发展方向。摄像机自标定相对于传统方法有更好的灵活性和实用性,通过十多年的不懈努力,理论上的问题已基本解决,目前研究的重点是如何提高标定算法的鲁棒性以及如何很好地用这些理论来解决实际视觉问题。为了提高鲁棒性,建议更多的使用分层逐步自标定方法,并应对自标定的结果进行线性优化。opencv标定程序的代码(完全测试好的)这个是我在win32平台下写的程序,测试完全通过:不过要注意下面的问题:(1)opencv库是1.0的,我在vc6.0的平台使用(2)软件的设置要正确(3)图片载入的时候,使用的是批处理文件(其实就是建一个txt文件,里面写的和dos下面的操作代码一样的输入)(4)里面现在还有个问题没有解决:在得到角点坐标的时候,cvFindCornerSubPix里面的搜索区域还不明白(05)下面是我在网上搜的别人的代:测试通过的:下面是我的代码:/*标定的过程:图片的加载角点的检测提取角点精确坐标参数求解利用参数对图像进行矫正*/#include<stdio.h>#include"cv.h"#include"highgui.h"#include<stdlib.h>//函数声明voidPrintMat(CvMat*matrix,BOOLsave_or_show,FILE*fp);intmain(intargc,char**argv){inti=1;chark=0;intCurrentImage=0;intCurrentRow=0;//行intCurrentColumn=0;//列intfindcorner_result=0;FILE*fp;//文件指针intChessBoardSize_w=6;//角点个数intChessBoardSize_h=7;intwidth_pixel=1280;//像素inthigh_pixel=1024;floatSquareSize=10;//棋盘大小intNImages=16;CvSizeChessBoardSize;CvSizeimage_pixel;intNPoints=0;int*corner_counter;float*temppoints;//这里可以使用内存动态存储管理。CvPoint2D32f*corners;//存储角点坐标的数组//单通道灰度图像IplImage*grayimage=0;IplImage*srcimage=0;//三通道图像IplImage*result_image=0;//矫正以后的图像CvMat*intrinsic_matrix=0;//内部参数矩阵CvMat*distortion_coeffs=0;//畸变系数CvMat*rotation_vectors=0;//旋转向量CvMat*translation_vectors=0;〃平移向量CvMat*points_counts=0;//图片角点数CvMat*object_points=0;//世界坐标系中角点的坐标CvMat*image_points=0;//检测到的角点坐标CvMat*temp_matrix,*rotation_matrix,*translation_matrix;//*****************************************************//数据载入、开辟空间image_pixel=cvSize(width_pixel,high_pixel);ChessBoardSize=cvSize(ChessBoardSize_w,ChessBoardSize_h);NPoints=ChessBoardSize_w*ChessBoardSize_h;corner_counter=calloc(NImages,sizeof(int));//动态管理,记着释放空间temppoints=calloc(NImages*NPoints*3,sizeof(float));corners=calloc(NImages*NPoints,sizeof(CvPoint2D32f));if((corner_counter==0)||(temppoints==0)||(corners==0)){return-1;}intrinsic_matrix=cvCreateMat(3,3,CV_32FC1);//内参数矩阵distortion_coeffs=cvCreateMat(1,4,CV_32FC1);//形变参数rotation_vectors=cvCreateMat(NImages,3,CV_32FC1);//旋转向量translation_vectors=cvCreateMat(NImages,3,CV_32FC1);//平移向量points_counts=cvCreateMat(NImages,1,CV_32SC1);//视图数目object_points=cvCreateMat(Nlmages*NPoints,3,CV_32FC1);//世界坐标系中角点的坐标image_points=cvCreateMat(Nlmages*NPoints,2,CV_32FC1);/检测到的坐标点坐标temp_matrix=cvCreateMat(1,3,CV_32FC1);rotation_matrix=cvCreateMat(3,3,CV_32FC1);//旋转矩阵translation_matrix=cvCreateMat(3,3,CV_32FC1);//旋转矩阵grayimage=cvCreateImage(image_pixel,IPL_DEPTH_8U,1);//单通道灰度图像result_image=cvCreateImage(image_pixel,IPL_DEPTH_8U,1);//校正以后的图像fp=fopen("data1.txt","w+");//打开文件,建立一个文件,然后写入数据fprintf(fp,"坐标数据:\n");〃写入数据,写入文件//****************************************************//图片的加载以及角点的提取if(argc!=NImages+1){printf("图片加载有误门;return-1;}for(CurrentImage=0;CurrentImage<NImages;CurrentImage++){//加载图片if((srcimage=cvLoadImage(argv[CurrentImage+1],1))!=0){//色彩转换cvCvtColor(srcimage,grayimage,CV_BGR2GRAY);//角点检测findcorner_result=cvFindChessboardCorners(grayimage,ChessBoardSize,&corners[CurrentImage*NPoints],&corner_counter[CurrentImage],CV_CALIB_CB_ADAPTIVE_THRESH);//画出检测到的点cvDrawChessboardCorners(srcimage,ChessBoardSize,&corners[CurrentImage*NPoints],corner_counter[CurrentImage],findcorner_result);//精确坐标位置cvFindCornerSubPix(grayimage,&corners[CurrentImage*NPoints],corner_counter[CurrentImage],cvSize(10,10),cvSize(-1,-1),〃这个搜索的范围。。?cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,500,0.003)/迭代终止条件);cvNamedWindow("image",1);cvShowImage("image",srcimage);printf('检测到的角点:%d\n",corner_counter[Currentlmage]);〃fprintf(fp,'检测到的角点:%d\n",corner_counter[Currentlmage]);〃for(i=0;i<corner_counter[Currentlmage];i++)//坐标输出//{//printf(""M%d个角点%f%f\n",i,corners[Currentlmage*NPoints+i].x,corners[Currentlmage*NPoints+i].y);//}cvWaitKey(0);printf("按任意键提取下一幅图片角点。。\n");〃fprintf(fp,"按任意键提取下一幅图片角点。。。\n");}}printf("角点提取结束……\n");printf("开始定标……\n");fprintf(fp,"角点提取结束……\n");fprintf(fp,"开始定标……\n");//棋盘世界坐标系坐标for(Currentlmage=0;Currentimage<NImages;Currentlmage++)//图片for(CurrentRow=0;CurrentRow<ChessBoardSize_h;CurrentRow++)/行{for(CurrentColumn=0;CurrentColumn<ChessBoardSize_w;CurrentColumn++)/列{temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3]=(float)(CurrentRow*SquareSize);temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3+1]=(float)(CurrentColumn*SquareSize);temppoints[(CurrentImage*NPoints*3)+(CurrentRow*ChessBoardSize_w+CurrentColumn)*3+2]=0;}}}//参数求解*object_points=cvMat(Nlmages*NPoints,3,CV_32FC1,temppoints);//以乎这里开始有点问题。。还有就是在标定过程中这个棋盘的边长和标定的精度无关cvSetData(image_points,corners,sizeof(CvPoint2D32f));//设置image_points矩阵的数据cvSetData(points_counts,corner_counter,sizeof(int));/*printf("棋盘坐标”);printf("\n");PrintMat(object_points);printf("\n计算机\n");printf("\n");PrintMat(image_points);printf("\n");printf("\n角点个数\n");PrintMat(points_counts);printf("\n");*/cvCalibrateCamera2(object_points,image_points,points_counts,cvGetSize(grayimage),intrinsic_matrix,distortion_coeffs,rotation_vectors,translation_vectors,0);printf("\n内部岑数矩阵\n");fprintf(fp,"\n内部岑数矩阵\n");PrintMat(intrinsic_matrix,FALSE,NULL);PrintMat(intrinsic_matrix,TRUE,fp);printf("\n形变岑数\n");fprintf(fp,"\n形变岑数\n");PrintMat(distortion_coeffs,FALSE,NULL);PrintMat(distortion_coeffs,TRUE,fp);for(i=0;i<NImages;i++){cvGetRow(rotation_vectors,temp_matrix,i);cvRodrigues2(temp_matrix,rotation_matrix,0);printf(”第%d(图片的旋转向量\n",i);fprintf(fp,"第%d个图片的旋转向量\n”,i);PrintMat(temp_matrix,FALSE,NULL);PrintMat(temp_matrix,TRUE,fp);printf("第%d(图片的旋转矩阵\n",i);fprintf(fp,"第%d个图片的旋转矩阵\n”,i);PrintMat(rotation_matrix,FALSE,NULL);PrintMat(rotation_matrix,TRUE,fp);printf("\n");fprintf(fp,"\n");}//cvReleaseMat(&temp_matrix);printf("平移矩阵\n");fprintf(fp,"平移矩阵\n");for(i=0;i<NImages;i++){cvGetRow(translation_vectors,temp_matrix,i);cvRodrigues2(temp_matrix,translation_matrix,0);printf("第%d(图片的平移向量\n",i);fprintf(fp,"第%d个图片的平移向量\n”,i);PrintMat(temp_matrix,FALSE,NULL);PrintMat(temp_matrix,TRUE,fp);printf("第%d(图片的平移矩阵\n",i);fprintf(fp,"第%d个图片的平移矩阵\n”,i);PrintMat(translation_matrix,FALSE,NULL);PrintMat(translation_matrix,TRUE,fp);printf("\n");fprintf(fp,"\n");}//PrintMat(translation_vectors,FALSE,NULL);//PrintMat(translation_vectors,TRUE,fp);printf("标定结束..…\n");fprintf(fp,"标定结束..…\n");printf('按任意键开始误差分析.•…\n");fprintf(fp,"按任意键开始误差分析..…\n");cvWaitKey(0);//误差分析〃利用已知的内部参数,使用cvProjectPoints2()计算出世界坐标系中的坐标在图片中的坐标也就是校准后的坐标//将校准后的坐标和原来求得的坐标进行比较for(CurrentImage=0;CurrentImage<NImages;CurrentImage++){CvMat*object_matrix=cvCreateMat(NPoints,3,CV_32FC1);CvMat*image_matrix=cvCreateMat(NPoints,2,CV_32FC1);CvMat*project_image_matrix=cvCreateMat(NPoints,2,CV_32FC1);CvMat*rotation_matrix_1=cvCreateMat(1,3,CV_32FC1);CvMat*translation_matrix_1=cvCreateMat(1,3,CV_32FC1);CvMat*rotation_matrix=cvCreateMat(3,1,CV_32FC1);CvMat*translation_matrix=cvCreateMat(3,1,CV_32FC1);doubleerr=0;cvGetRows(object_points,object_matrix,CurrentImage*NPoints,(CurrentImage+1)*NPoints,1);cvGetRow(rotation_vectors,rotation_matrix_1,CurrentImage);cvReshape(rotation_matrix_1,rotation_matrix,0,3);cvGetRow(translation_vectors,translation_matrix_1,CurrentImage);cvReshape(translation_matrix_1,translation_matrix,0,3);cvGetRows(image_points,project_image_matrix,CurrentImage*NPoints,(CurrentImage+1)*NPoints,1);cvProjectPoints2(object_matrix,rotation_matrix,translation_matrix,intrinsic_matrix,distortion_coeffs,image_matrix,0,0,0,0,0);err=cvNorm(image_matrix,project_image_matrix,CV_L2,0);printf("第%d幅图像的误差为%f\n",Currentlmage+1,err);fprintf(fp,"第%d幅图像的误差为%f\n",Currentlmage+1,err);}cvNamedWindow("Undistort_image",1);//显示校正后的图片printf("\n");printf("校正后的图片.…\n");for(CurrentImage=0;CurrentImage<NImages;CurrentImage++){//加载图片if((srcimage=cvLoadImage(argv[CurrentImage+1],1))!=0){//色彩转换cvCvtColor(srcimage,grayimage,CV_BGR2GRAY);cvUndistort2(grayimage,result_image,intrinsic_matrix,distortion_coeffs);cvShowImage("Undistort_image",result_image);printf("按任意键显示下一幅图片。。。\n");cvWaitKey(0);}//关闭文件fclose(fp);//释放内存cvWaitKey(0);free(corner_counter);free(
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 江西省吉安市新干县第二中学2025年高三第一次模拟考试化学试卷含解析
- 慢性肾病患者教育
- 宁夏回族自治区银川市长庆高级中学2025年高三一诊考试化学试卷含解析
- 2025年理线器合作协议书
- 2025届山东省济南市历城区济钢高级中学高三考前热身化学试卷含解析
- 护理品管圈的心得
- 河南省信阳市光山县第二高级中学2024-2025学年高一下学期3月第一次月考生物学试题(含答案)
- 2025年海南省省直辖县级行政单位琼中黎族苗族自治县中考一模历史试题(含答案)
- 2025年HITECOAT高耐蚀耐磨化学镀镍磷合金钢板材项目发展计划
- SYB甜品店创业计划书
- 掌握重点中职电子商务教师资格证试题与答案
- 5.3基本经济制度 课件 2024-2025学年统编版道德与法治八年级下册
- 河南省郑州市管城区2024-2025学年级九年级下学期第一次模拟数学试题(原卷版+解析版)
- 隔音涂料施工方案
- 甘肃卷2024年高考真题化学试题(含答案)
- T-CCTAS 61-2023 桥梁承重缆索抗火密封综合防护技术规程
- 消防员职业技能鉴定中级技能题库大全
- 铁路行车组织 课件 项目4 调车工作
- 2024年浙江邮电职业技术学院高职单招职业技能测验历年参考题库(频考版)含答案解析
- (一模)2024-2025学年佛山市普通高中教学质量检测(一)数学试卷(含答案)
- 招标代理机构选取突发情况应急处理预案
评论
0/150
提交评论