在和openCV的camera calibration亲切玩耍了两周后,来和大家分享一下经验:
讨论项目在...\opencv\sources\samples\cpp\tutorial_code\calib3d\camera_calibration
1.我在做啥:
----看到花里胡哨地标定过程逐渐迷失自我.jpg
简而言之,廉价相机”凸眼看人弯“,于是乎我们用神秘的数学方法来修正这个问题。
openCV的教程文件里是这样的:
看了一眼,看不懂--没关系,这并不重要,重要的是:你知道了这个项目最终给了你九个重要的数字。
畸变参数(distortion coefficients)
相机矩阵 (camera martix)
获得这些参数后,不论我们用这个相机(相同焦距)拍出了多扭曲的N张照片,我们都能通过召唤openCV的这两个函数来initUndistortRectifyMap,remap 来修正我们的图片了。
2. 具体点,咋获得参数
简单,拿出你的国际象棋棋盘,假装这是你臭美的gf,对着她一阵咔擦咔擦,各种姿态咔个二十来张,喂给程序就OK了。
比如这样:
。。。。。。
3. 项目中止咋回事
如果项目中止,出现interrupt,那多半是你的输入值搞错了。
让我们来讨论三个输入输出文件:
在in_VID5.xml文件里,有三个至关重要的值:棋盘长(BoardSize_Height)、宽(BoardSize_Width),以及输入取样文件路径的位置(input)。输入错误,项目无法运行。
棋盘长宽是内角格数(如下图,长宽为6*4);文件路径是找到VID5.xml的绝对路径(absolute path)。
VID5.xml里面装的是所有照片的储存路径。如果在标定棋盘中(draw the corner),突然停止,那么就是多半是你取样的文件路径输错了,即VID5.xml中的一串图片地址有误。
具体数据会保存在一个叫outputs_para.xml的文件里:
3. 校正结果
当图像扭曲不是特别明显时,校正图似乎和原图(未校正的失真图)会看起来没多大差别。现在,注意校正图的四边是否有多出黑色边缘,若有则是校正过的表现。这是因为镜头将图像部分边缘拉伸,还原后,边缘没取到像素的位置设成黑色边界。
如果你校正后的图比没矫正还要扭曲,那么必然是矫正用的参数有问题。参数有问题,那就是取样的过程中出了毛病。请注意,校正的范围并不是根据棋盘纸在镜头视野内的相对大小来决定的。整张图片均会被“校正”。
当整张棋盘纸皆在拍摄视野范围内时,都能得出较合理校正结果—问题是校正精度不同。
当棋盘纸格子超过镜头范围,则该照片内角无法被提取。
4. 关于畸变参数的一个问题
回顾一下畸变参数(distortion coefficients):
畸变参数分为两种:切向畸变(tangential distortion)和径向畸变(radial distortion)。
切向形变是这样的:
简言之,镜头和物体不平行,长方形拍成梯形。
径向形变是这样的:
就是直线变弯。
(上两图均来自别处)
然后,k1,k2,k3是负责径向畸变(直线变弯的);p1,p2是负责切向畸变的(镜头不平行的)。
比较坑的是,虽然openCV提到了切向畸变的参数p1,p2,但是整个标定结束后并没有给出他俩的值
所以,切向实际上是不管的。
有些时候,这个要紧,有时候并不,看你需求。
如果你想修正一下这个,也许你会说,那没事,我把镜头弄放平行就行了。没错,这样也行。但是有些廉价工业摄像机的镜头凸透镜没粘水平,所以可能,镜头看似水平而实非水平。
切向畸变 - 国内版 Bing images(引用图片)
(完)
BTW,有人想知道我是怎么愚蠢地处理切向校正的吗?