python 三维重构库 python 三维重建_python 三维重构库

opencv实现标定校准工作

参考https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html

python 三维重构库 python 三维重建_github_02

标定图片需要使用标定板在不同位置、不同角度、不同姿态下拍摄。在前面的博客中进行推导时,我们分析得知至少要有3张图片,才能有唯一解。通常以10~20张为佳。

通常都会购买专门的标定板,如果精度要求不高,也可以自己打印。 网上也有别人已经拍好的照片,下面是下载链接:https://pan.baidu.com/s/1mhG3mHU

程序中就直接使用这些现成的图片来测试了,省事。一共有14张图片。

python 三维重构库 python 三维重建_python opencv 三维重建_03

python 三维重构库 python 三维重建_github_04

python的格式返回一个ret和corner。

python 三维重构库 python 三维重建_python 三维重构库_05

这个我们已经见识过了。

python 三维重构库 python 三维重建_python_06

python 三维重构库 python 三维重建_python_07

如果patterWasFound是真,就会有连线。

python 三维重构库 python 三维重建_python 三维重构库_08

如果是false

python 三维重构库 python 三维重建_python opencv 三维重建_09

就没有连线。这个是又找了一张的测试图,内焦点也还不错。这里我觉得选内角点的时候最好全部选择,上面的(6,4)就是这么选择的,这因为zhe'g棋盘是我们选择的,我们当然是知道横竖有多少个角点了。

python 三维重构库 python 三维重建_python opencv 三维重建_10

如果选择的不对是会报错的。少了会报错,ret直接就是False。

python 三维重构库 python 三维重建_python 三维重构库_11

多给了虽然能画出来图,不过ret也还是false,这个结果还是有问题的。

python 三维重构库 python 三维重建_python opencv 三维重建_12

函数:

python 三维重构库 python 三维重建_python opencv 三维重建_13

python 三维重构库 python 三维重建_github_14

objectponit我们只需要给世界坐标系的X,Y的坐标,因为Z=0。imagePoints就是像素坐标系中角点的坐标。flags里面是标定的一些算法,LM方法其实是一种非最小二乘法。

python 三维重构库 python 三维重建_python 三维重构库_15

上一讲提出的问题我在这里其实还是有一定的疑问,就是k1,k2的初值是如何确定的?

python 三维重构库 python 三维重建_python 三维重构库_16

其实我们可以不用知道未畸变的棋盘是什么样的,只用4个在一条直线上的点就可以了。因为棋盘在一条直线上的点的间距应该是一样的,就根据这一点列方程。

python 三维重构库 python 三维重建_世界坐标系_17

假设有上面4个点,Ai对应的点是(xi,yi),离主点的距离是ri,这些我们都可以知道。那么我们就可以列方程了,每三个点可以一个方程:

python 三维重构库 python 三维重建_世界坐标系_18

关于y也可以列方程,不过那个和x的系数一样,因为都是ri^2的差或者说和x列的方程是齐次的。这样就可以解出k1,k2。不过可能每张图我们可能不止四个点,而且不止一张图,这个时候我们就用最小二乘法求k1,k2了。这里我们解决了如何求k1,k2初值的问题,后面还是要进行极大似然估计,但是这个初值对于LM算法还是比较重要的。我们如果要标定还需要考虑抑恶个问题,就是棋盘坐标在世界坐标系的坐标,Z坐标是0我们知道了。其它坐标我们如何确定呢?我们就随便定咯,这里我们知道的是棋盘的方格是10*10的。

python 三维重构库 python 三维重建_python opencv 三维重建_19

那么:

python 三维重构库 python 三维重建_github_20

mgrid是meshgrid的缩写。是生成坐标网格,输入的参数是坐标范围,得到的网格的点坐标。

python 三维重构库 python 三维重建_python opencv 三维重建_21

这个ret据说就是极大似然函数的那个最小值。

python 三维重构库 python 三维重建_github_22

mtx是内参矩阵,我们看到c=0。

python 三维重构库 python 三维重建_python_23

这个旋转用的的旋转向量的形式,因为用了14张图,所以有14组外参数。

python 三维重构库 python 三维重建_python opencv 三维重建_24

python 三维重构库 python 三维重建_python 三维重构库_25

这个是把世界坐标系投影到像素坐标系,因为其实是求解一个非线性最小二乘,误差函数不可能是0的,所以肯定会有一些偏差的。

python 三维重构库 python 三维重建_世界坐标系_26

这个计算出来之后,可以计算一下平均平方误差,cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2),这个误差也可以叫做重投影误差,这个是评价相机标定结果的一个指标。

python 三维重构库 python 三维重建_python 三维重构库_27

结果是0.033,这个结果看起来还是不错的。上面是完成标定工作了,并且还对标定结果作出了评价。据官方文档说,这个ret也可以是一个指标。

python 三维重构库 python 三维重建_世界坐标系_28

RMS就是

python 三维重构库 python 三维重建_python opencv 三维重建_29

不过还是有点不太一样,但是差的很少,一个是0.16,一个是0.18。

python 三维重构库 python 三维重建_python_30

下面介绍一个模块,叫做glob。

python 三维重构库 python 三维重建_python 三维重构库_31

需要注意的是这个不会迭代查找,它不会去子文件夹中继续查找。

python 三维重构库 python 三维重建_python 三维重构库_32

这种通配符的用法就是*代表任意个(很多个)任意字符而?代表一个字符。

python 三维重构库 python 三维重建_python 三维重构库_33

我没有觉得iglob有什么存在的必要。关于查找文件,我们在学习python的时候就已经将结果如何去查找某一个类型的文件,后来我们又学了正则表达式,就可以不仅仅是查找某种类型的文件了,那个时候我们学的是可以递归查找的。

python 三维重构库 python 三维重建_python opencv 三维重建_34

opencv校正图像

undistortion就是去畸变的意思,distortion是畸变的意思。

上面我们已经完成了标定工作,但是没有对图片进行校正,下面我们要做的事校正工作。opencv有两个函数可以校正图像。我们下面都会看到,在那之前,我们可以用cv2.getOptimalNew优化一下相机内参数矩阵,我觉得这一步做的就是把畸变的形式和相机内矩阵的形式结合一下,得出一个新的相机内参矩阵。

python 三维重构库 python 三维重建_github_35

python 三维重构库 python 三维重建_python_36

python 三维重构库 python 三维重建_github_37

python 三维重构库 python 三维重建_github_38

python 三维重构库 python 三维重建_python 三维重构库_39

python 三维重构库 python 三维重建_python opencv 三维重建_40

也就是调整alhpa的值主要还是为了调整显示范围,也就是ROI。

python 三维重构库 python 三维重建_python_41

cameraMatrix是上面张氏标定得出的相机内参矩阵,distCoeffs是畸变向量,ImageSize是原始输入图像的大小,alpha就是调整输出图像区域的一个值,如果为0,就只会保留校正后的像素,如果为1,就会保留所有像素,就会出现那些黑色区域。validPixROi是校正后比较好的区域的一个矩形参数。centerPrincipalPoint,这个参数说的是是否要把主点移动到图像平面中心。

python 三维重构库 python 三维重建_python_42

undistort是校正的函数。

python 三维重构库 python 三维重建_世界坐标系_43

其实我们上面的失真向量里面的值都比较小。

python 三维重构库 python 三维重建_python_44

校正的时候为什么需要用到相机内参矩阵呢?因为计算r的时候是计算和主点的距离,所以需要用到内参数的u0和v0参数。我们来试一试。

python 三维重构库 python 三维重建_python opencv 三维重建_45

其实这两个矩阵差别不大,主要还是我们的畸变向量的值都比较小,这个主点也不是正好在中间。

python 三维重构库 python 三维重建_python 三维重构库_46

这个应该能看懂什么意思。

python 三维重构库 python 三维重建_python 三维重构库_47

由于我们的畸变向量的参数都很小。基本上看不出来什么区别。

python 三维重构库 python 三维重建_世界坐标系_48

如果不用这个getOptimalNewCameraMatrix呢?

python 三维重构库 python 三维重建_世界坐标系_49

还是因为我这个图片基本上畸变很小,看不出来。

试试第二种方式吧。

python 三维重构库 python 三维重建_世界坐标系_50

python 三维重构库 python 三维重建_python_51

python 三维重构库 python 三维重建_github_52

python 三维重构库 python 三维重建_python_53

用getOptimalNewCameraMatrix:

python 三维重构库 python 三维重建_python 三维重构库_54

不用:

python 三维重构库 python 三维重建_python_55

可以看出区别,如果不用,右边就多出来一列黑色的地带。

python 三维重构库 python 三维重建_python_56

mapx,mapy里面存的是原来的480*640个像素校正之后的位置。

这个5不能随便改动。

python 三维重构库 python 三维重建_世界坐标系_57

python 三维重构库 python 三维重建_python_58

张正友标定和校正就到这里了。

其实github速度也不慢的:

python 三维重构库 python 三维重建_python opencv 三维重建_59

github地址:https://github.com/lcl1026504480/opencv-python-turorial

码云地址:https://gitee.com/lcl1026504480/opencv-python-turorial